c strncpy null 是否终止
c strncpy null terminated or not
我正在阅读 this 文档,它说:
char *strncpy(char *destination, const char *source, size_t num);
Copy characters from string
Copies the first num
characters of source
to destination
. If the end of the source
C string (which is signaled by a null-character) is found before num
characters have been copied, destination
is padded with zeros until a total of num
characters have been written to it.
No null-character is implicitly appended at the end of destination if source is longer than num
. Thus, in this case, destination
shall not be considered a null terminated C string (reading it as such would overflow).
destination
and source
shall not overlap (see memmove
for a safer alternative when overlapping).
但我对这个说法感到困惑:
in this case, destination shall not be considered a null terminated C string (reading it as such would overflow)
因为如果num > strlen(source)
,它会在末尾填充'[=26=]'
,'[=26=]'
实际上是一个字符串中的空(终止)字符,为什么它不应该被认为是一个以 null 结尾的 C 字符串?
我写了下面的代码来验证:
char from[] = { 'h', 'e', 'l', 'l', 'o', '[=11=]' };
char to[1024];
for (int i = 0; i < 1024; i++) {
to[i] = 'e';
}
strncpy(to, from, 1024);
printf("from %s\n", from);
它在以下输出下工作正常:
from hello
to hello
说的是 strlen(source)
> num
的情况。它只会复制 num
个字符,其中 none 个是 NUL,并且不会添加 NUL。
strncpy(dst, src, len)
仅在前 len
字节内的 src
中存在空终止符时才向 dst
添加空终止符。您的代码似乎可以工作,因为数组 to[]
之后可能有也可能没有空字符。更好的测试是:
char source[] = "source";
char dest[] = "destination";
strncpy(dest, source, 6);
printf("%s\n", dest);
结果应该是:
sourceation
如果您改写 strncpy(dest, source, 7)
,则输出只是单词 source
。
strncpy()
的语义,即使在上面的 C++ 参考中进行了精确解释,也被广泛误解。此函数的行为违反直觉且容易出错。
为了避免在使用它或进一步开发过程中出现问题,当维护者会误读代码并添加更多微妙的错误时,有一个简单的解决方案:永远不要使用这个功能.
您可以在 this article by Bruce Dawson 中阅读有关此内容的更多详细信息。
回答你的问题:如果源字符串长于作为第三个参数传递的大小(通常对应于目标缓冲区的大小),该函数会将 size 个字符复制到目标并且不会有空字节存在于其中。然后调用 strlen(destination);
将调用未定义的行为,因为它将尝试读取超出数组末尾的内容,直到找到空终止符。这种特定行为是 strncpy
如此容易出错的原因。
我正在阅读 this 文档,它说:
char *strncpy(char *destination, const char *source, size_t num);
Copy characters from string Copies the first
num
characters ofsource
todestination
. If the end of thesource
C string (which is signaled by a null-character) is found beforenum
characters have been copied,destination
is padded with zeros until a total ofnum
characters have been written to it.No null-character is implicitly appended at the end of destination if source is longer than
num
. Thus, in this case,destination
shall not be considered a null terminated C string (reading it as such would overflow).
destination
andsource
shall not overlap (seememmove
for a safer alternative when overlapping).
但我对这个说法感到困惑:
in this case, destination shall not be considered a null terminated C string (reading it as such would overflow)
因为如果num > strlen(source)
,它会在末尾填充'[=26=]'
,'[=26=]'
实际上是一个字符串中的空(终止)字符,为什么它不应该被认为是一个以 null 结尾的 C 字符串?
我写了下面的代码来验证:
char from[] = { 'h', 'e', 'l', 'l', 'o', '[=11=]' };
char to[1024];
for (int i = 0; i < 1024; i++) {
to[i] = 'e';
}
strncpy(to, from, 1024);
printf("from %s\n", from);
它在以下输出下工作正常:
from hello
to hello
说的是 strlen(source)
> num
的情况。它只会复制 num
个字符,其中 none 个是 NUL,并且不会添加 NUL。
strncpy(dst, src, len)
仅在前 len
字节内的 src
中存在空终止符时才向 dst
添加空终止符。您的代码似乎可以工作,因为数组 to[]
之后可能有也可能没有空字符。更好的测试是:
char source[] = "source";
char dest[] = "destination";
strncpy(dest, source, 6);
printf("%s\n", dest);
结果应该是:
sourceation
如果您改写 strncpy(dest, source, 7)
,则输出只是单词 source
。
strncpy()
的语义,即使在上面的 C++ 参考中进行了精确解释,也被广泛误解。此函数的行为违反直觉且容易出错。
为了避免在使用它或进一步开发过程中出现问题,当维护者会误读代码并添加更多微妙的错误时,有一个简单的解决方案:永远不要使用这个功能.
您可以在 this article by Bruce Dawson 中阅读有关此内容的更多详细信息。
回答你的问题:如果源字符串长于作为第三个参数传递的大小(通常对应于目标缓冲区的大小),该函数会将 size 个字符复制到目标并且不会有空字节存在于其中。然后调用 strlen(destination);
将调用未定义的行为,因为它将尝试读取超出数组末尾的内容,直到找到空终止符。这种特定行为是 strncpy
如此容易出错的原因。