strncat()总是在末尾加上空字符吗?

7

考虑以下代码:

limit = sizeof(str1)-strlen(str1)-1;
strncat(str1,str2,limit);

如果str2的长度大于limitstrncat是否会将str1以Nul结尾,还是我需要像strncpy一样添加这段代码?
str1[sizeof(str1)-1] = '\0'

你确定 str1 是数组类型,对吧? - Sourav Ghosh
你必须明确指出str1是一个数组。 - Sourav Ghosh
str1 是如何声明的?我们可以猜测,但要注意,对于不熟悉可能出现的问题的人来说,他们将使用您的代码并且会遇到问题。目前,如果 str1 是一个 char *,那么您的代码将失败(可能是惊人的)。 - Jongware
请注意,strncat并不是strcat的更安全的版本。 - Dietrich Epp
1
@SouravGhosh:strncpy函数截断字符串,而strcpy函数则不会。它们是具有不同目的的不同函数,使用其中任何一个来替换另一个都没有意义。如果您不想默默地截断字符串,但正在使用strncpy因为它更“安全”,那么您应该重新评估您的代码安全策略。strcat_s函数确实被设计为strcat的更安全版本,但普遍共识是它未能实现这一目标,应该使用组合替代技术(如代码插装)代替。 - Dietrich Epp
显示剩余2条评论
2个回答

10

它总是以空字符结尾。

引用 C11,第§7.24.3.2章节,(重点强调

strncat函数将从由s2指向的数组中追加不超过n个字符(不附加空字符及其后面的字符)到由s1指向的字符串的结尾。 s2的初始字符覆盖了s1末尾的空字符。最终始终会添加一个空字符。

以及,脚注

因此,指向s1的数组中最多可以出现strlen(s1)+n+1个字符。


3
strncat可能会让人感到困惑,因为 'n' 是指源字符串而不是目标缓冲区。因此,这个函数仍然是不安全的,可能会导致溢出。大多数其他的'n'变体都是为了防止溢出而创建的,这也是我之前所感到困惑的原因。 - Petr

-2

C++版本低于C11时,在源字符串没有足够空间的情况下,不会在类似的情况下追加空字符到目标字符串中。

char str[5];
str="Ami"

char str2[10];
str2="NotGoing"

str 只有 2 个空闲位置,但需要 7 个空间来连接 str2,并需要额外的 1 个字符来作为 null 终止符。 在不使用 null 终止符的情况下,使用 strncat(str, str2, )。

如果没有足够的空间将整个目标字符串 (str2) 与预先写入的数据一起写入 str 中,则不会在结尾处添加 null 字符。

char str[10];
str="Ami"

char str2[3];

str2="Hello"

str已经有足够的空间容纳str2,因此在末尾添加一个空字符。

strncat(str,str2,);// case with null termination.

这是我自己制作的正式表格

分配给 str 的长度 >= strlen(str)+ strlen(str2)+1 ;

如果满足此条件,您将获得一个以 null 结尾的结果,否则您将不会。


1
C11是C标准,C++是C++。C++版本低于C11这部分语法上是不正确的,任何C++标准版本都不会比任何C标准版本高或低。C++ strncat文档指出:结果字节串以空字符结尾。如果你的实现没有这样做,那么你的strncat实现就不符合标准。如果你向strncat的第一个指针传递的内存不足,那么你将遇到未定义的行为,并访问超出数组边界,程序将变得不正常。 - KamilCuk
据我所知,会发生缓冲区溢出,但答案是它不会在末尾添加空字符。 - Amit Sharma
1
在缓冲区溢出的情况下,会发生未定义行为,因此 strncat 会在您的房间中生成恶魔。对于未定义行为应该/将会发生什么做任何假设都是错误的。我认为,在未定义行为的情况下,任何实现都可以写入一个空终止字符,如果它想要的话。如果您假设在未定义行为中会发生某些事情,那么您就不再谈论 C 语言了。 - KamilCuk
我告诉你这个是因为我在我的当前项目中遇到了这个问题。虽然不能透露代码。 - Amit Sharma
你是对的,Kamil Cuk,在使用strncpy时确实会出现这个问题。我道歉。 - Amit Sharma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接