#include <stdio.h>
#include <string.h>
int main()
{
const char* source = "dog";
char destination[4] = "cat";
printf("source is %s\n", source);
printf("destination is %s\n", destination);
/* the strlen+1 accounts for null termination on source */
/* but you need to be sure that source can fit into destination */
/* and still be null terminated - (that's on you the programmer) */
strncpy(destination, source, strlen(source) + 1);
printf("source is still %s\n", source);
printf("destination is now %s\n", destination);
return 0;
}
4条答案
按热度按时间i86rm4rw1#
根本不应使用
strncpy
和strncat
函数。它们的名字以
str
开头,但它们实际上并不处理字符串。在C中,字符串被定义为“以'\0'
结尾的字符序列“。这些函数并不保证得到的字符数组总是以null结尾。更好的替代方案是
strlcpy
和strlcat
,但它们并不是到处都可用。更好的办法是建立一个独立的字符串库,在其中确定字符串的长度是一个恒定时间的操作,但这会分散注意力。
ldioqlga2#
正如torstenvl提到的,
"cat"
和"dog"
是字符串常量,所以这里没有正确使用函数,第一个参数是destination,第二个参数是source,第三个参数是要复制的字节数。来源:开放组基础规范- strncpy
要回答您的具体问题:是;空终止符被复制到目标字符串。
n
字节被写入,并且如果你的源字符串s2
比n
字节短,NULL
被填充直到n
字节被写入。在你的问题中,看起来像是你在尝试追加两个字符串。要在C语言中这样做,你需要首先分配一个源字符串缓冲区,复制第一个字符串,然后从第二个字符串的末尾开始复制第二个字符串。根据你最后一步的开始位置,你可以得到“catdog\0”或者“cat\0dog\0”。2这是典型的“off by one”错误的另一个例子。
首先,你必须计算两个你想要追加的字符串的长度,你可以使用
strlen
,fromstring.h
来计算。strlen
不把空终止符作为长度的一部分,所以记住,要得到最后一个字符串的长度,你必须使用strlen(s1) + strlen(s2) + 1
。然后你可以像往常一样复制第一个字符串。复制第二个字符串的一个简单方法是这样做:
然后,您可以执行
strncpy(s2start, s2, [the size of s2])
,这样您就知道您是从s1空终止符开始的,从而避免了“cat\0dog”错误。希望这能帮上忙,祝你好运。
vwoqyblh3#
当你在c中写出一个像
"cat"
或"dog"
这样的字符串时,数组是不能改变的,如果你试图改变它会导致未定义的行为。你只能在一个函数需要const char * input
时使用这些数组,const
告诉你它不能/不会在函数中改变。当你写"dog"
时,字符数组中的数据看起来像这样:请注意,它以NUL终止。
您正在使用的函数:
将
src
复制到dst
,最大长度为n
,您无法复制到"cat"
。如上所述,您可以看到char *dest
不是常量,但const char * src
是常量。因此源可能是"cat"
或"dog"
如果要为字符串分配空间,则允许修改它:
现在字符数组
cat_str
被初始化为"cat"
,但是我们可以随时更改它,注意它的长度将是4(每个字母一个,加上一个NUL),因为我们没有指定长度。所以请确保不要更改cat_str[3]之后的任何内容,您可以通过0到3对它进行索引s71maibg4#
一些静态分析工具有一个常见的误解,认为
strncpy
是strcpy
的一个更安全的版本。事实并非如此,它有一个不同的目的。如果我们坚持使用它来防止缓冲区溢出,你需要认识到一个事实,即对于它的签名如果
source
比num
长,则destination
的末尾不会隐式附加空字符。因此,在这种情况下,destination
不应被视为以空结尾的C字符串(这样阅读它会溢出)。所以如果你知道你的源代码是一个以空结尾的C字符串,那么你可以做以下事情: