strncpy文档问题

发布于 2024-10-13 08:44:19 字数 301 浏览 3 评论 0原文

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

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

这句话是什么意思呢?

At the following regarding strncpy: http://www.cplusplus.com/reference/clibrary/cstring/strncpy/, it mentions the following:

No null-character is implicitly appended to the end of destination, so destination will only be null-terminated if the length of the C string in source is less than num.

What is meant by this sentence?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

并安 2024-10-20 08:44:19

这意味着,例如,如果源字符串有 20 个字符加上 null 终止符,而 strncpy 指定的字符少于 21 个字符,则目标字符串不会附加 null。

这是因为它的工作方式: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)设置为 null。

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

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

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

It means that, for example, if your source string is 20 characters plus a null terminator and your strncpy specifies less than 21 characters, the target string will not have a null appended to it.

It's because of the way it works: strncpy guarantees that it will write exactly N bytes where N is the length value passed in.

If the length of the source string (sans null byte) is less than that, it will pad the destination area with nulls. If it's equal or greater, you won't get a null added to the destination.

That means it may not technically be a C string that you get. This can be solved with code like:

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.

You allocate 11 bytes (array indexes 0..10), copy up to 10 (indexes 0..9) then set the 11th (index 10) to null.

Here's a diagram showing the three possibilities for writing various-sized strings to a 10-character area with strncpy (d, s, 10) where . represents a null byte:

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

Note that in the second and third case, no null byte is written so, if you treat d as a string, you're likely to be disappointed in the outcome.

瑾夏年华 2024-10-20 08:44:19

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

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

The string "foo" has 3 characters + 1 null-terminator (it's stored as "foo\0") giving a total length of 4. If you call strncpy with n=3 (or fewer) it won't append a null-terminator to the end of the target string, but will copy only "foo". Attempting to print the resulting string will result in undefined behaviour due to the lack of a null-terminator which signals the end of the string.

You have to be very careful of this and either pass n one greater than the maximum source or add the null-terminator yourself.

江湖彼岸 2024-10-20 08:44:19

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

That means that it copies the terminating null of the source string, but doesnt add a terminating null if the source string doesnt fit into the destination.

雄赳赳气昂昂 2024-10-20 08:44:19

在 C 中,字符串存储为 char 数组,并且它们以 null 结尾,这意味着它们在末尾附加了一个额外的 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 结尾的,则无法知道其长度,并且大多数字符串操作函数都会失败或会执行意外操作。

In C strings stored as arrays of char's and they are null-terminated, which means they have an extra 0 appended at the end, which marks the end of the string and could be used later to figure out the string's length. So the string "hello" looks like this in memory:

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

Normally, when you copy a string, the null character should be copied as well. So the memory needed for the string buffer is its length + 1 (e.g. (strlen(hello) + 1) * sizeof(char)).

Function strncpy allows you to copy only as many characters as it's possible to fit in the provided buffer. In case the buffer you provided is not big enough to hold that extra null, it won't be added. Or if the string is cut, it won't be null-terminated.

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

You should be always careful after calling strncpy, since the result might not be a valid C string. If the string is not null-terminated it's impossible to know its length and most of the string manipulation functions would fail or would do something unexpected.

漫漫岁月 2024-10-20 08:44:19

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

建议使用 strlcpy 代替。

It means that only num bytes will be copied from the source buffer to the destination buffer; so if the source string length if upper or equal to num, the terminating NULL byte will not be copied, and the result will not have a NULL terminating byte, which is dangerous.

It is recommended to use strlcpy instead.

神仙妹妹 2024-10-20 08:44:19

strncpy() 的语义,即使按照上面的 C++ 参考中的那样进行了精确解释,仍然被广泛误解。该函数的行为违反直觉且容易出错。

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

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

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

The semantics of strncpy(), even when precisely explained as they are in the C++ reference above, are widely misunderstood. The behavior of this function is counterintuitive and error prone.

To avoid problems when using it or further down the development process, when the maintainer will misread the code and add more subtile bugs, there is a simple solution: NEVER EVER USE THIS FUNCTION.

You can read further details about this in this article by Bruce Dawson.

To answer your question: if the source string is longer than the size passed as a third argument (usually corresponding to the size of the destination buffer), the function will copy size characters to the destination and no null byte will be present among these. Calling strlen(destination); will then invoke undefined behavior because it will attempt to read beyond the end of the array until it finds a null terminator. This specific behavior is what makes strncpy so error prone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文