c strncpy null是否终止

时间:2016-12-08 17:20:10

标签: c strncpy

我正在阅读this文件,它说:

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

从字符串中复制字符    将num的前source个字符复制到destination。如果在复制source个字符之前找到num C字符串的结尾(由空字符表示),则{0}填充destination,直到总共num 1}}字符已写入其中。

     

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

     

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

但我对此声明感到困惑:

  

在这种情况下,destination不应被视为空终止的C字符串(读取它会溢出)

因为如果num > strlen(source)在最后填充'\0''\0'实际上是字符串中的空(终止)字符,为什么它不应被视为空 - 终止了C字符串?

我在下面写了一些代码来验证:

  char from[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
  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

3 个答案:

答案 0 :(得分:6)

正在谈论strlen(source)&gt;时的情况。 num。它只会复制num个字符,其中没有一个是NUL,也不会添加NUL。

答案 1 :(得分:5)

如果strncpy(dst, src, len)字节中的dst内存在空终止符,则

src仅向len添加空终止符。您的代码似乎可以工作,因为在数组to[]之后可能有也可能没有空字符。更好的测试是:

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

结果应为:

sourceation

如果您改为编写strncpy(dest, source, 7),则输出只是单词source

答案 2 :(得分:3)

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

为了避免在使用它或进一步开发过程中出现问题,当维护者误读代码并添加更多的漏洞时,有一个简单的解决方案:从未使用过这个功能

您可以在this article by Bruce Dawson中阅读有关此内容的更多详情。

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