如何使用指针从不同的函数访问本地variables?

我可以在不同的函数中访问局部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()函数中的整个数组才能访问它比第一次?

myArray是一个局部variables,因此指针只有在它的作用域(在这种情况下是包含函数getArray )的末尾才有效。 如果您稍后访问,则会出现未定义的行为。

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

要修复你的代码,你需要在足够长的作用域(在你的例子中是main函数)中声明数组,或者将它分配到堆上。 如果你在堆上分配它,你需要手动释放它,或者使用RAII在C ++中释放它。

我错过了一个替代scheme(可能是最好的一个,如果数组不是太大的话)就是把你的数组包装到一个结构中,从而使它成为一个值types。 然后返回它创build一个幸存的函数返回的副本。 有关详细信息,请参阅tp1的答案 。

一旦超出范围,您将无法访问本地variables。 这是什么意思是一个局部variables。

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

您需要将数组数据存储在堆上并传递一个指针,或者保存在一个范围内的variables(例如全局函数或主函数内的某个范围)。

尝试类似的东西。 如果它在本地定义,则“杀死” 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; } 

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

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

局部variables返回时超出范围,所以你不能返回一个指向局部variables的指针。

你需要dynamic分配它(在堆上),使用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手段,阅读这个问题和答案 。

正确的做法如下:

 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()函数的作用域消失了,并且每个从该作用域所需要的值都需要被复制到调用作用域。

在这段代码中,你已经使用了指向本地对象的指针,但是当一个函数返回所有局部variables超出了作用域。 如果您将分配内存(使用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; } 

这段代码将打印所有的数组元素,不会发生覆盖。

C ++解决scheme:

“我可以用不同的函数访问局部variables吗?如果是这样,怎么办?

答案是否定的,而不是在函数结束之后。 局部variables在那个时候被销毁。

C++中,处理返回数组的方式是在容器中像std :: array (fixed size)或std :: vector (dynamic size)那样pipe理它们。

例如:

 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; } 

在第二个函数中,返回的值由编译器进行了优化,所以您不需要付出实际复制数组的代价。