C strncpy null 终止与否



我正在阅读这份文档,它说:

char *strncpy(char *destination, const char *source, size_t num);

从字符串中复制字符 将source的前num个字符复制到destination。如果在复制num字符之前找到sourceC 字符串(由空字符表示信号)的末尾,则用零填充destination,直到总共写入了num个字符。

如果源的长度超过num条,则不会在目标末尾隐式附加空字符。因此,在这种情况下,destination不应被视为以空结尾的 C 字符串(这样读取它会溢出)。

destinationsource不得重叠(有关重叠时更安全的替代方案,请参阅memmove)。

但我对这种说法感到困惑:

在这种情况下,不应将目标视为以空结尾的 C 字符串(这样读取它会溢出)

既然如果num > strlen(source),它会在末尾用''填充,''实际上是字符串中的空(终止)字符,为什么它不应该被视为以空结尾的 C 字符串?

我写了下面的代码来验证:

char from[] = { 'h', 'e', 'l', 'l', 'o', '' };
char to[1024];
for (int i = 0; i < 1024; i++) {
to[i] = 'e';
}
strncpy(to, from, 1024);
printf("from %sn", from);

它适用于以下输出:

from hello
to hello

它说的是strlen(source)>num的情况。 它只会复制num个字符,其中没有一个是 NULL,也不会添加 NUL。

strncpy(dst, src, len)仅在前len个字节内src中存在空终止符时才向dst添加一个空终止符。您的代码似乎有效,因为数组to[]之后可能有也可能没有空字符。更好的测试是:

char source[] = "source";
char dest[] = "destination";
strncpy(dest, source, 6);
printf("%sn", dest);

结果应该是:

sourceation

如果你写strncpy(dest, source, 7),那么输出只是单词source

strncpy()的语义,即使按照上面C++参考文献中的精确解释,也被广泛误解。此函数的行为违反直觉且容易出错。

为了避免在使用它时或进一步开发过程中出现问题,当维护者误读代码并添加更多子错误时,有一个简单的解决方案:永远不要使用这个函数

您可以在Bruce Dawson的这篇文章中阅读有关此内容的更多详细信息。

回答您的问题:如果源字符串的长度大于作为第三个参数传递的大小(通常对应于目标缓冲区的大小),则该函数会将大小字符复制到目标,并且其中不会出现空字节。 然后,调用strlen(destination);将调用未定义的行为,因为它将尝试读取数组末尾之外的内容,直到找到 null 终止符。 这种特定行为使strncpy如此容易出错。

相关内容

  • 没有找到相关文章

最新更新