一个有趣的例子

这是一个C语言的例子:

void init_array() {
    int arr[10];
    for (int i = 0; i < 10; ++i) {
        arr[i] = i;
    }
}

void print_array() {
    int arr[10];
    for (int i = 0; i < 10; ++i) {
       printf("%ld\t", arr[i]);
    }
}

int main() {
    init_array();
    print_array();
}

代码中init_arrayprint_array各自有一个长度为10的局部数组arrinit_array把它内部的arr初始化成0~9,print_array把它内部的arr遍历输出到控制台,然后在main函数中对它们进行调用。

print_array执行后输出到控制台:

0    1    2    3    4    5    6    7    8    9

结果有点让人疑惑,似乎这两个函数有着某种关系。

现在取消对init_array的调用,再看下结果:

177988    32765    5497827    21857    2157688    32518    9257904    21857    0    0

这次输出了随机值,因为C/C++并不会初始化内存中的值,这些值都是上一次使用这些内存的程序留下的。

对比两次结果发现init_array确实对print_array中的数组arr产生了影响。init_arrayprint_array中的arr看起来都各自独立,为什么会出现这种情况?

来看下这两个函数各自在返回前的栈帧结构:

可以发现它们的栈帧结构和大小完全一样。init_array执行完之后它的栈帧被销毁,但是原来的值还在内存中。当print_array执行时继续给它分配了同一块内存且栈帧结构也一样,这样就把init_array在内存中遗留的数据拿到了。

我们对代码稍作修改,让这两个函数都把各自arr在内存中的地址输出到控制台:

void init_array() {
    int arr[10];
    printf("%p\n", arr);
}

void print_array() {
    int arr[10];
    printf("%p", arr);
}

int main() {
    init_array();
    print_array();
}

控制台结果:

0x7ffd2aaf3ff0
0x7ffd2aaf3ff0

结果再一次印证了这两个arr被放到了是同一块栈内存中。所以print_array输出了原先在init_arrayarr的值。

results matching ""

    No results matching ""