void func(){
int i;
char str[100];
strcat(str, "aa");
printf("%s\n", str);
}
int main(){
func();
func();
func();
return 0;
}
此代码打印:
?@aa
?@aaaa
?@aaaaaa
我不明白为什么会创建垃圾value(?@)
,以及为什么"aa"
会被连续追加。理论上应该在功能终止时销毁本地值。但是这段代码没有。
答案 0 :(得分:1)
要使用strcat()
,您需要有一个有效的字符串,未初始化的char
数组不是有效的字符串。
要使其成为有效的“空”字符串,您需要执行此操作
char str[100] = {0};
这会创建一个空字符串,因为它只包含 null 终结符。
使用strcat()
时要小心。如果你想两个只是连接到有效的c字符串就可以了,如果它们超过2那么它就不是正确的功能,因为它的方式就是它。
此外,如果您希望代码正常工作,请在main()
中声明数组并将其传递给函数,就像这样
void
func(char *str)
{
strcat(str, "aa");
printf("%s\n", str);
}
int
main()
{
char str[100] = {0};
func(str);
func(str);
func(str);
return 0;
}
答案 1 :(得分:1)
标准中没有任何内容表明堆栈上的数据需要被破坏"当函数返回时。这是undefined behavior,这意味着任何事情都可能发生。
某些实现可能会选择将零写入堆栈中的所有字节,有些可能会选择在那里写入随机数据,而有些可能会选择不接触它。
在这个特定的实现上,似乎它没有尝试清理堆栈上的内容。
第一次调用func
后返回。堆栈中的数据仍然存在,因为它还没有被覆盖。当您在第一次调用后立即再次调用func
时,str
变量恰好位于与之前相同的物理内存中。由于在调用函数中没有进行其他函数调用,因此该数据在第一次调用时保持不变。
如果要在调用func
之间调用其他函数,那么您很可能会看到不同的行为,因为str
将包含其他任何函数使用的数据被称为最后一次。
答案 2 :(得分:0)
函数strcat
表示连接两个strings
。因此函数的两个参数必须表示字符串。此外,第一个论点也发生了变化。
字符数组表示一个字符串,您可以使用字符串文字(可能是“空”字符串文字)初始化它,也可以隐式地在数组初始化时或初始化后指定零值。
例如
void func(){
char str1[100] = "";
char str2[100] = {'\0'};
char str3[100];
str3[0] ='\0';
//...
}
请注意,具有自动存储持续时间的对象不会隐式初始化。他们有不确定的价值观。
关于你的问题
为什么函数中没有销毁本地数组值?
然后原因是数组占用的内存没有被其他函数覆盖。但无论如何,它都是未定义的行为。
答案 3 :(得分:0)
宣布:
$f_for = "'%".$filter_for."%'";
你所做的只是声明一个字符数组,但它是随机垃圾。
所以你实际上是在追加垃圾。
如果你这样做了:
char str[100];
然后你会得到不同的结果,因为字符串将以null开头。无论何时在C中分配内存,除非在分配内存时对其进行初始化,否则它只会是当时内存中的内存。您不能认为它将为NULL并为您提供零。