为什么本地数组值不会在函数中被破坏?

时间:2016-02-05 15:24:07

标签: c

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"会被连续追加。理论上应该在功能终止时销毁本地值。但是这段代码没有。

4 个答案:

答案 0 :(得分:1)

要使用strcat(),您需要有一个有效的字符串,未初始化的char数组不是有效的字符串。

要使其成为有效的“”字符串,您需要执行此操作

char str[100] = {0};

这会创建一个空字符串,因为它只包含 null 终结符。

使用strcat()时要小心。如果你想两个只是连接到有效的字符串就可以了,如果它们超过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并为您提供零。