6

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

没有空字符隐式附加到目标的末尾,因此只有当源中 C 字符串的长度小于 num 时,目标才会以空字符结尾。

这句话是什么意思?

4

6 回答 6

13

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

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

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

下图显示了将各种大小的字符串写入 10 个字符的区域的三种可能性,strncpy (d, s, 10)其中 where.表示空字节:

s              d
-------------  ----------
Hello.         Hello.....
Hello Fred.    Hello Fred
Hello George.  Hello Geor

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

于 2011-01-22T14:13:23.543 回答
5

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

您必须非常小心这一点,要么传递n大于最大源的 1,要么自己添加空终止符。

于 2011-01-22T14:12:31.140 回答
4

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

于 2011-01-22T14:11:57.747 回答
4

在存储为char's 数组的 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 字符串。如果字符串不是以空值结尾的,就不可能知道它的长度,并且大多数字符串操作函数都会失败或会做一些意想不到的事情。

于 2011-01-22T14:23:23.987 回答
1

这意味着只有num字节会从源缓冲区复制到目标缓冲区;所以如果源字符串的长度大于num等于

建议使用strlcpy代替。

于 2011-01-22T14:17:18.737 回答
0

的语义strncpy(),即使在上面的 C++ 参考中得到了准确的解释,也被广泛误解。此函数的行为违反直觉且容易出错。

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

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

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

于 2016-12-09T21:41:12.547 回答