strncpy介绍了一个有趣的角色

strncpy介绍了一个有趣的角色,c,strncpy,C,Strncpy,当我在我的机器上运行一些代码时,它的行为就像我期望的那样 当我在同事身上运行它时,它的行为不正常。事情就是这样 我有一个值为的字符串: croc_数据_0001.idx 当我对字符串执行strncpy时,提供18作为复制字符串的长度值: croc_数据_0001.idx♂ 如果我这样做 myCopiedString[18]='\0'; puts (myCopiedString); 则复制的字符串的值为: croc_数据_0001.idx 导致此问题的原因是什么?为什么将最后一个字符设置为\0?

当我在我的机器上运行一些代码时,它的行为就像我期望的那样

当我在同事身上运行它时,它的行为不正常。事情就是这样

我有一个值为的字符串:

croc_数据_0001.idx

当我对字符串执行
strncpy
时,提供18作为复制字符串的长度值:

croc_数据_0001.idx♂

如果我这样做

myCopiedString[18]='\0';
puts (myCopiedString);
则复制的字符串的值为:

croc_数据_0001.idx


导致此问题的原因是什么?为什么将最后一个字符设置为
\0

strncpy
并不总是添加
\0。
请参阅

因此,要么事先清除目标缓冲区,要么总是自己添加
\0
,或者使用
strcpy

如果问题是:“为什么我的机器上未初始化的内存的内容与另一台机器上的不同”,那么,人们只能猜测

编辑稍微改变了措辞;参见注释。

根据

将源的第一个num字符复制到目标。如果结束 源C字符串(由空字符表示)的 在复制num字符之前找到,填充目标 直到总共写入num个字符为止。 没有空字符隐式附加到目的地的末尾,因此只有当长度 源中C字符串的长度小于num


因此,您需要用“\0”手动终止您的目的地。

为myCopiedString变量分配了多少空间?如果大于源字符串的长度,请确保使用bzero清除目标变量。

strncpy
不希望复制字符串的大小,而希望复制目标缓冲区的大小

在您的情况下,目标缓冲区太短,将
strncpy
禁用为零以终止字符串。因此,字符串后面的所有内容都是。位置18且不为零将被视为属于该字符串

通常,采用缓冲区大小的函数的调用正好是这样的,即。e

char dest[50];
strncpy(dest, "croc_data_0001.idx", sizeof dest);
加上这个和一个额外的

dest[sizeof dest - 1] = '\0';

字符串总是以0结尾。

我认为C标准比其他人发布的链接更清楚地描述了这个函数

ISO 9899:2011

7.24.2.4 strncpy功能

strncpy函数复制的字符数不超过n个(null后面的字符 字符(不复制)从s2指向的数组复制到s1指向的数组。如果复制发生在重叠的对象之间,则行为未定义

如果s2指向的数组是短于n个字符的字符串,则为空字符 追加到s1指向的数组中的副本,直到总共添加了n个字符 书面的


strncpy
无法正确终止目标字符串。它不是用来替代strcpy的!另外,未定义的行为(使用非字符串的
printf
put
)也可以像您期望的那样表现出来;)另一方面,调试生成倾向于“零出”未初始化的内存,因此这也可能会影响结果(即,它在调试模式下工作正常,但在发布模式下显示奇怪的字符)。是的,它会自动添加\0,但仅在“n”没有缓冲区大的情况下。“用零填充”意味着在所有未使用的内存单元上添加空终止。C++引用的词性很差。好的,除了你的意思是“只有N”,“源字符串”更大!否。如果您有
str[2]
strncpy(str,“hi”,2)
,则n=2,n与缓冲区一样大。尾随“\0”没有剩余空间,因此未添加任何空间(错误)。strcpy()会尝试在缓冲区外写入尾随“\0”,然后使程序崩溃(错误)。
strncpy
与缓冲区的大小无关。它的功能不是为strcpy提供“缓冲区大小安全”的替代方案,而是将较大字符串的片段复制到其他字符串中。编写这些函数时,不存在“防止缓冲区溢出”的概念。我的观点是,在我的示例中,传递的字符串是3字节,但n=2。问题并不是说目标缓冲区的大小,所以你不能从中得出结论。不,但如果我取给
strncpy()的值
作为目标缓冲区大小(从这个函数的角度来看,就是这样),我只能得出这样的结论。
dest[sizeof dest - 1] = '\0';
char *strncpy (char * restrict s1,
               const char * restrict s2,
               size_t n);