strncpy
,在http://www.cplusplus.com/reference/clibrary/cstring/strncpy/中提到:
目标字符串不会自动添加空字符,所以只有当源字符串的长度小于 num 时,目标字符串才以空字符结尾。
这句话是什么意思?
strncpy
,在http://www.cplusplus.com/reference/clibrary/cstring/strncpy/中提到:
目标字符串不会自动添加空字符,所以只有当源字符串的长度小于 num 时,目标字符串才以空字符结尾。
这句话是什么意思?
这意味着,例如,如果您的源字符串是20个字符加上一个空终止符,而您的strncpy
指定少于21个字符,则目标字符串将不会附加空终止符。
这是因为它的工作方式:strncpy
保证将写入确切的N个字节,其中N是传递的长度值。
如果源字符串(不包括空字节)的长度小于该值,则它将用null填充目标区域。如果它等于或大于该值,则不会在目标中添加null。
这意味着您可能得到的不是严格意义上的C字符串。可以通过像这样的代码解决:
char d[11]; // Have enough room for string and null.
strncpy (d, s, 10); // Copy up to 10 bytes of string, null the rest.
d[10] = '\0'; // Then append null manually in case s was too long.
你分配了11个字节(数组索引为0..10),最多复制10个(索引为0..9),然后将第11个(索引为10)设置为null。
这里是一个图示,展示了使用strncpy (d,s,10)
将各种大小的字符串写入10个字符区域的三种可能性,其中.
表示空字节:
s d
------------- ----------
Hello. Hello.....
Hello Fred. Hello Fred
Hello George. Hello Geor
请注意,在第二和第三种情况下,没有写入null字节,因此,如果您将d
视为字符串,则可能会对结果感到失望。
d[10]
实际上 不会 被填充。复制 10 个字节将填充 d[0]
到 d[9]
(包括),留出 d[10]
用作 null。这就是为什么要声明它为 int d[11]
(0
到 10
)。更新回答以澄清。 - paxdiablo"foo"
有3个字符+1个空终止符(存储为"foo\0"
),总长度为4。如果你使用n=3
(或更少)调用strncpy
,它将不会在目标字符串的末尾附加一个空终止符,只会复制"foo"
。由于缺少标志字符串结束的空终止符,尝试打印结果字符串将导致未定义的行为。n
传递为源字符串中字符的最大值加1,要么自己添加空终止符。char
数组,它们以空字符结尾,也就是说,在字符串的末尾添加了一个额外的0
,用于标记字符串的结尾,并且可以在后面用来确定字符串的长度。因此,字符串"hello"
在内存中的样子如下:char hello[] = {'h', 'e', 'l', 'l', 'o', 0};
通常情况下,当你复制一个字符串时,null
字符也应该被复制。因此,字符串缓冲区所需的内存为其长度加1(如:(strlen(hello) + 1) * sizeof(char)
)。
strncpy
函数允许你仅复制能够适合提供的缓冲区中的字符数量。如果你提供的缓冲区不足以容纳这个额外的null
,它将不会被添加。或者,如果字符串被截断,则不会以null结尾。
char hello[] = "hello"; // 5 characters, 6 bytes long
char hel[3];
strncpy(hel, hello, 3); // hel is {'h', 'e', 'l'}
在调用strncpy
后,您应该始终小心,因为结果可能不是有效的C字符串。如果字符串没有以空字符结尾,那么它的长度是无法确定的,大多数字符串操作函数将失败或执行意外操作。
* sizeof(char)
,这会增加您键盘的按键次数和显示器所需的电子数量,从而缩短它们的寿命 :-) - paxdiablosizeof(hello[0])
。 - detunizednum
字节,因此如果源字符串长度大于或等于 num
,则终止的 NULL 字节将不会被复制,结果将不包括 NULL 结尾字节,这是危险的。strncpy()
的语义即使在C++参考文献中被准确地解释,也经常被误解。这个函数的行为是反直觉的,容易出错。
为了避免在使用它或在开发过程中出现问题,当维护者误读代码并添加更多微妙的错误时,有一个简单的解决方案:永远不要使用这个函数。
您可以在Bruce Dawson的这篇文章中阅读更多详细信息。
回答您的问题:如果源字符串比作为第三个参数传递的大小(通常对应于目标缓冲区的大小)长,则该函数将复制大小个字符到目标位置,并且这些字符中没有空字节。调用strlen(destination);
将会引起未定义的行为,因为它将尝试读取数组末尾之外的内容,直到找到空终止符。这种特定的行为使得strncpy
非常容易出错。
strncpy
作为安全的strcpy
,它是一种不同目的的函数,容易导致其他安全风险。 - Matteo Italia