C语言局部数据指针

如果你不理解程序栈如何工作,就很容易犯返回指向局部数据的指针的错误。在下面的例子中,我们重写了3.2.4节中用到的allocateArray函数。这次我们不为数组动态分配内存,而是用了一个局部数组:

int* allocateArray(int size, int value) {
    int arr[size];
    for(int i=0; i<size; i++) {
        arr[i] = value;
    }
    return arr;
}

不幸的是,一旦函数返回,返回的数组地址也就无效了,因为函数的栈帧从栈中弹出了。尽管每个数组元素仍然可能包含45,但如果调用另一个函数,就可能覆写这些值。下面的代码段对此做了演示,重复调用printf函数导致数组损坏:

int* vector = allocateArray(5,45);
for(int i=0; i<5; i++) {
    printf("%d\n", vector[i]);
}

图3-6说明了发生这种情况时内存的分配状态。虚线框表示其他的栈帧(比如printf函数用到的),可能会被推到程序栈上,从而损坏数组持有的内存。栈帧的实际内容取决于实现。

返回局部数据的指针

还有一种方法是把arr变量声明为static。这样会把变量的作用域限制在函数内部,但是分配在栈帧外面,避免其他函数覆写变量值。

int* allocateArray(int size, int value) {
    static int arr[5];
    ...
}

不过这种方法并不一定总是有用。每次调用allocateArray函数都会重复利用这个数组。这样相当于每次都把上一次调用的结果覆盖掉。此外,静态数组必须声明为固定长度,这样会限制函数处理变长数组的能力。

如果函数只是返回一个可能的值,而且共享这些值也不会有什么坏处,那么它可以维护一个这些值的列表,然后返回合适的值。如果我们需要返回状态类型的消息,比如不大可能被修改的错误码,这么做就很有用。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程