strncat, strncat_s
|
定义于头文件
<string.h>
|
||
| (1) | ||
|
char
*
strncat
(
char
*
dest,
const
char
*
src,
size_t
count
)
;
|
(C99前) | |
|
char
*
strncat
(
char
*
restrict
dest,
const
char
*
restrict
src,
size_t
count
)
;
|
(C99起) | |
|
errno_t strncat_s
(
char
*
restrict
dest, rsize_t destsz,
const char * restrict src, rsize_t count ) ; |
(2) | (C11起) |
src
指向的字符数组最多追加
count
个字符(若遇到空字符则停止)到
dest
指向的以空字符结尾的字节字符串末尾。字符
src
[
0
]
将覆盖
dest
末尾的空终止符。最终总会追加一个终止空字符(因此函数可能写入的最大字节数为
count
+
1
)。
dest
的内容和
src
的前
count
个字符及终止空字符,则行为未定义。若源对象与目标对象重叠,则行为未定义。若
dest
不是指向空终止字节字符串的指针,或
src
不是指向字符数组的指针,则行为未定义。
destsz
),且在运行时检测到以下错误时会调用当前安装的
约束处理函数
:
-
-
src或dest是空指针 -
destsz或count为零或大于 RSIZE_MAX -
在
dest的前destsz字节中不存在空字符 -
将发生截断:
count或src长度(取较小者)超过dest的空终止符与destsz之间的可用空间 - 源字符串与目标字符串之间会出现重叠
-
dest
所指向的字符数组大小 <
strnlen
(
dest,destsz
)
+
strnlen
(
src,count
)
+
1
<
destsz
,则行为未定义;换言之,错误的
destsz
值不会暴露即将发生的缓冲区溢出。如果
src
所指向的字符数组大小 <
strnlen
(
src,count
)
<
destsz
,则行为未定义;换言之,错误的
count
值不会暴露即将发生的缓冲区溢出。
-
与所有边界检查函数一样,仅当实现定义了
__STDC_LIB_EXT1__
且用户在包含
<string.h>
之前将
__STDC_WANT_LIB_EXT1__
定义为整型常量
1
时,才保证
strncat_s可用。
目录 |
参数
| dest | - | 指向要追加内容的以空字符结尾的字节字符串的指针 |
| src | - | 指向要复制的字符数组的指针 |
| count | - | 要复制的最大字符数 |
| destsz | - | 目标缓冲区的大小 |
返回值
dest
的副本
dest
是空指针,或
destsz
为零或大于
RSIZE_MAX
)。
注释
由于
strncat
每次调用时都需要定位到
dest
的末尾,因此使用
strncat
将多个字符串连接成一个字符串的效率较低。
尽管截断以适应目标缓冲区是一种安全风险,因此对
strncat_s
构成运行时约束违规,但通过将
count
指定为目标数组大小减一仍可实现截断行为:该函数将始终复制前
count
个字节并附加空终止符:
strncat_s
(
dst,
sizeof
dst, src,
(
sizeof
dst
)
-
strnlen_s
(
dst,
sizeof
dst
)
-
1
)
;
示例
#define __STDC_WANT_LIB_EXT1__ 1 #include <string.h> #include <stdio.h> #include <stdlib.h> int main(void) { char str[50] = "Hello "; char str2[50] = "World!"; strcat(str, str2); strncat(str, " Goodbye World!", 3); puts(str); #ifdef __STDC_LIB_EXT1__ set_constraint_handler_s(ignore_handler_s); char s1[100] = "good"; char s5[1000] = "bye"; int r1 = strncat_s(s1, 100, s5, 1000); // r1 为 0,s1 存储 "goodbye\0" printf("s1 = %s, r1 = %d\n", s1, r1); char s2[6] = "hello"; int r2 = strncat_s(s2, 6, "", 1); // r2 为 0,s2 存储 "hello\0" printf("s2 = %s, r2 = %d\n", s2, r2); char s3[6] = "hello"; int r3 = strncat_s(s3, 6, "X", 2); // r3 非零,s3 存储 "\0" printf("s3 = %s, r3 = %d\n", s3, r3); // strncat_s 截断惯用法: char s4[7] = "abc"; int r4 = strncat_s(s4, 7, "defghijklmn", 3); // r4 为 0,s4 存储 "abcdef\0" printf("s4 = %s, r4 = %d\n", s4, r4); #endif }
可能的输出:
Hello World! Go s1 = goodbye, r1 = 0 s2 = hello, r2 = 0 s3 = , r3 = 22 s4 = abcdef, r4 = 0
参考文献
- C23 标准 (ISO/IEC 9899:2024):
-
- 7.26.3.2 strncat 函数 (p: 379)
-
- K.3.7.2.2 strncat_s 函数 (p: TBD)
- C17 标准 (ISO/IEC 9899:2018):
-
- 7.24.3.2 strncat 函数 (页: 265-266)
-
- K.3.7.2.2 strncat_s 函数 (页: 449-450)
- C11 标准 (ISO/IEC 9899:2011):
-
- 7.24.3.2 strncat 函数 (p: 364-365)
-
- K.3.7.2.2 strncat_s 函数 (p: 618-620)
- C99标准(ISO/IEC 9899:1999):
-
- 7.21.3.2 strncat函数(页码:327-328)
- C89/C90 标准 (ISO/IEC 9899:1990):
-
- 4.11.3.2 strncat 函数
参见
|
(C11)
|
连接两个字符串
(函数) |
|
(C11)
|
将一个字符串复制到另一个字符串
(函数) |
|
(C23)
|
将一个缓冲区复制到另一个缓冲区,在指定分隔符后停止
(函数) |
|
C++ 文档
for
strncat
|
|