如何使用指针从不同的函数访问局部变量?

时间:2010-12-31 13:27:56

标签: c++ c pointers local-variables

我可以在不同的函数中访问本地变量吗?如果是这样,怎么样?

void replaceNumberAndPrint(int array[3]) {
    printf("%i\n", array[1]);
    printf("%i\n", array[1]);
}

int * getArray() {
    int myArray[3] = {4, 65, 23};
    return myArray;
}

int main() {
    replaceNumberAndPrint(getArray());
}

以上代码的输出:

65
4202656

我做错了什么? “4202656”是什么意思?

我是否必须在replaceNumberAndPrint()函数中复制整个数组才能比第一次更多地访问它?

10 个答案:

答案 0 :(得分:56)

myArray是一个局部变量,因此指针只有在其范围结束时(在这种情况下,包含函数getArray)才有效。如果以后访问它,则会出现未定义的行为。

实际上,对printf的调用会覆盖myArray使用的堆栈部分,然后包含其他一些数据。

要修复代码,您需要在足够长的范围内声明数组(示例中为main函数),或者在堆上分配它。如果在堆上分配它,则需要手动释放它,或者使用RAII在C ++中释放它。

我错过了一个替代方案(可能是这里最好的一个,只要数组不是太大)就是将数组包装成一个结构,从而使它成为一个值类型。然后返回它会创建一个在函数返回后幸存的副本。有关详细信息,请参阅tp1answer

答案 1 :(得分:18)

一旦超出范围,您就无法访问本地变量。这就是本地变量的含义。

当您在replaceNumberAndPrint函数中访问数组时,结果是未定义的。它似乎第一次工作的事实只是一个幸运的巧合。可能你指向的内存位置是在堆栈上未分配的,并且仍然为第一次调用正确设置,但是对printf的调用然后通过在操作期间将值推入堆栈来覆盖它,这就是为什么第二次调用printf会显示某些内容不同。

您需要将数组数据存储在堆上并传递指针,或者传递到保留在范围内的变量(例如,全局或主函数中的某些范围)。

答案 2 :(得分:8)

尝试类似的东西。如果它本地定义,你执行它的方式“杀死”myArray会导致。

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
 printf("%i\n", array[0]);
 printf("%i\n", array[1]);
 printf("%i\n" , array[2]);
 free(array);
}

int * getArray() {
 int * myArray = malloc(sizeof(int) * 3);
 myArray[0] = 4;
 myArray[1] = 64;
 myArray[2] = 23;
 //{4, 65, 23};
 return myArray;
}

int main() {
 replaceNumberAndPrint(getArray());
}

更多:http://www.cplusplus.com/reference/clibrary/cstdlib/malloc/

编辑:正如评论所指出:更好的方法是:

#include <stdio.h>
#include <stdlib.h>

void replaceNumberAndPrint(int * array) {
    if(!array)
        return;

    printf("%i\n", array[0]);
    printf("%i\n", array[1]);
    printf("%i\n" , array[2]);
}

int * createArray() {
    int * myArray = malloc(sizeof(int) * 3);

    if(!myArray)
        return 0;

    myArray[0] = 4;
    myArray[1] = 64;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int * array = createArray();
    if(array)
    {
        replaceNumberAndPrint(array);
        free(array);
    }
    return 0;
}

答案 3 :(得分:2)

离开getArray后,myArray会超出范围。你需要在堆上为它分配空间。

答案 4 :(得分:2)

您的代码调用未定义的行为,因为只要myArray返回getArray()超出范围,并且任何尝试使用(取消引用)悬空指针都是UB。

答案 5 :(得分:2)

返回时局部变量超出范围,因此您无法返回指向局部变量的指针。

您需要使用mallocnew动态地(在堆上)分配它。例如:

int *create_array(void) {
    int *array = malloc(3 * sizeof(int));
    assert(array != NULL);
    array[0] = 4;
    array[1] = 65;
    array[2] = 23;
    return array;
 }
 void destroy_array(int *array) {
     free(array);
 }
 int main(int argc, char **argv) {
     int *array = create_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     destroy_array(array);
     return 0;
 }

或者,您可以将数组声明为静态,请记住语义不同。例如:

int *get_array(void) {
    static int array[] = { 4, 65, 23 };
    return array;
 }
 int main(int argc, char **argv) {
     int *array = get_array();
     for (size_t i = 0; i < 3; ++i)
         printf("%d\n", array[i]);
     return 0;
 }

如果您不知道static的含义,请阅读this question & answer

答案 6 :(得分:2)

正确的方法如下:

struct Arr {
   int array[3];
};
Arr get_array() {
   Arr a;
   a.array[0] = 4;
   a.array[1] = 65;
   a.array[2] = 23;
   return a;
}
int main(int argc, char **argv) {
   Arr a = get_array();
   for(size_t i=0; i<3; i++)
       printf("%d\n", a.array[i]);
   return 0;
}

要了解为什么需要这样做,您需要知道sizeof(数组)的工作原理。 C(以及c ++)努力避免复制数组,你需要结构来超越它。为什么需要复制是因为范围 - get_array()函数的范围消失,并且需要将该范围仍然需要的每个值复制到调用范围。

答案 7 :(得分:0)

在此代码中,您使用了指向本地对象的指针,但是当函数返回时,所有局部变量都超出了范围。如果你将分配内存(使用malloc()函数进行分配),那么任何数据都不会丢失或覆盖。

int* getArray(int size) {
    int *myArray = (int*)malloc(size*sizeof(int));
    myArray[0] = 4;
    myArray[1] = 65;
    myArray[2] = 23;
    return myArray;
}

int main() {
    int i;
    int *vector = getArray(3);
    for(i=0;i<3;i++)
    {
        printf("%i\n",vector[i]);
    }
    getch();
    return 0;
}

此代码将打印所有数组元素,不会覆盖。

答案 8 :(得分:0)

C ++解决方案:

  

&#34;我可以在不同的函数中访问局部变量吗?如果是这样,怎么样?&#34;

答案是否定的,不是在功能结束后。那时局部变量被破坏。

C++中,处理返回数组的方法是在容器中管理它们,如std::array(固定大小)或std::vector(动态)尺寸)。

例如:

void replaceNumberAndPrint(const std::array<int, 3>& array) {
    printf("%i\n", array[0]);
    printf("%i\n", array[1]);
    printf("%i\n", array[2]);
}

std::array<int, 3> getArray() {
    std::array<int, 3> myArray = {4, 65, 23};
    return myArray;
}

在第二个函数中,返回值由编译器优化,因此您不必为实际复制数组付出代价。

答案 9 :(得分:0)

.c内的静态..or ..全局会成功;)

但是程序在整个时间中将占用这3个字节,但是您避免在类似这样的简单事情上进行malloc(建议对大数组使用malloc)

另一方面,如果外部函数修改了指针,则内部“ myArray”将被修改,因为它指向它,就是这样

for (var i = 0; i < auditTables.length; i++)