strncpy文档问题

时间:2011-01-22 14:08:40

标签: c++ c strncpy

关于strncpyhttp://www.cplusplus.com/reference/clibrary/cstring/strncpy/的以下内容,它提到了以下内容:

  

没有空字符隐式附加到目标的末尾,因此如果源中的C字符串的长度小于num,则目标将仅以空值终止。

这句话是什么意思?

6 个答案:

答案 0 :(得分:10)

这意味着,例如,如果源字符串是20个字符加上空终止符,并且strncpy指定少于21个字符,则目标字符串不会附加空值。

这是因为它的工作方式:strncpy保证它会写出N个字节,其中N是传入的长度值。

如果源字符串(sans null byte)的长度小于该值,则它将使用空值填充目标区域。如果它等于或大于,则不会将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

请注意,在第二种和第三种情况下,不会写入空字节,因此,如果将d视为字符串,则可能会对结果感到失望。

答案 1 :(得分:5)

字符串"foo"有3个字符+ 1个空终结符(它存储为"foo\0"),总长度为4.如果您使用strncpy调用n=3(或者更少)它不会在目标字符串的末尾附加一个空终止符,但只会复制"foo"。尝试打印结果字符串将导致未定义的行为,因为缺少一个表示字符串结尾的空终止符。

您必须非常小心这一点,并将n传递给大于最大来源的一个或自己添加空终结符。

答案 2 :(得分:4)

这意味着它复制源字符串的终止空值,但如果源字符串不适合目标,则不会添加终止空值。

答案 3 :(得分:4)

在作为char的数组存储的C字符串中,它们以空值终止,这意味着它们在末尾附加了额外的0,这标志着字符串的结尾,可能是后来用来计算字符串的长度。所以字符串"hello"在内存中看起来像这样:

char hello[] = {'h', 'e', 'l', 'l', 'o', 0};

通常,复制字符串时,也应复制null字符。所以字符串缓冲区所需的内存是它的长度+ 1(例如(strlen(hello) + 1) * sizeof(char))。

函数strncpy允许您只复制尽可能多的字符以适合提供的缓冲区。如果您提供的缓冲区不足以容纳额外的null,则不会添加它。或者,如果字符串被剪切,它将不会以空值终止。

char hello[] = "hello"; // 5 characters, 6 bytes long
char hel[3];
strncpy(hel, hello, 3); // hel is {'h', 'e', 'l'}

调用strncpy后应始终小心,因为结果可能不是有效的C字符串。如果字符串不是以null结尾,则无法知道它的长度,并且大多数字符串操作函数都会失败或者会发生意外情况。

答案 4 :(得分:1)

这意味着只有num字节将从源缓冲区复制到目标缓冲区;因此,如果源字符串长度大于或等于num,则不会复制终止空字节,结果将不会有一个NULL终止字节,这很危险。

建议改为使用strlcpy

答案 5 :(得分:0)

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

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

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

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