How to access a local variable from a different function using pointers?
我可以访问不同函数中的局部变量吗?如果是这样,怎么办?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void replaceNumberAndPrint(int array[3]) { printf("%i ", array[1]); printf("%i ", array[1]); } int * getArray() { int myArray[3] = {4, 65, 23}; return myArray; } int main() { replaceNumberAndPrint(getArray()); } |
上述代码的输出:
1 2 | 65 4202656 |
我做错什么了?"4202656"是什么意思?
我是否必须复制
实际上,对
要修复代码,您需要在足够长的作用域(示例中的
我遗漏的一个选择(可能是这里最好的一个,前提是数组不太大)是将数组包装成一个结构,从而使它成为一个值类型。然后返回它会创建一个在函数返回之后仍然存在的副本。有关详细信息,请参阅TP1的答案。
一旦超出范围,就不能访问局部变量。这就是局部变量的含义。
在replacenumberandprint函数中访问数组时,结果未定义。这似乎是第一次奏效,这只是一个幸运的巧合。可能您指向的内存位置在堆栈上未分配,并且仍然为第一个调用正确设置,但对printf的调用随后会通过在堆栈操作期间将值推送到堆栈来覆盖此位置,这就是第二个对printf的调用显示不同的内容的原因。
您需要将数组数据存储在堆中并传递一个指针,或者保存在作用域中的变量中(例如全局变量或主函数中作用域的某个变量)。
尝试类似的方法。你这样做会"杀死"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <stdio.h> #include <stdlib.h> void replaceNumberAndPrint(int * array) { printf("%i ", array[0]); printf("%i ", array[1]); printf("%i " , 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/
编辑:正如评论正确指出的那样:更好的方法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #include <stdio.h> #include <stdlib.h> void replaceNumberAndPrint(int * array) { if(!array) return; printf("%i ", array[0]); printf("%i ", array[1]); printf("%i " , 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; } |
正确的方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 ", a.array[i]); return 0; } |
要理解为什么需要这样做,您需要知道sizeof(array)是如何工作的。C(因此C++)努力避免复制数组,而你需要Strut通过它。为什么需要复制是因为作用域——get_array()函数的作用域消失了,该作用域中仍然需要的每个值都需要复制到调用作用域。
局部变量在返回时超出范围,因此不能返回指向局部变量的指针。
您需要使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 ", array[i]); destroy_array(array); return 0; } |
或者,您可以将数组声明为静态的,记住语义是不同的。例子:
1 2 3 4 5 6 7 8 9 10 11 | 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 ", array[i]); return 0; } |
如果您不知道
您的代码调用未定义的行为,因为
离开GetArray后,MyArray就超出范围。您需要在堆上为它分配空间。
C++解决方案:
"May I have any access to a local variable in a different function? If so, how?"
答案是"否",而不是在函数结束后。此时局部变量被销毁。
在
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | void replaceNumberAndPrint(const std::array<int, 3>& array) { printf("%i ", array[0]); printf("%i ", array[1]); printf("%i ", array[2]); } std::array<int, 3> getArray() { std::array<int, 3> myArray = {4, 65, 23}; return myArray; } |
在第二个函数中,编译器对返回值进行了优化,因此您不必为实际复制数组付出代价。
在这段代码中,您使用了指向局部对象的指针,但是当函数返回时,所有局部变量都超出范围。如果要分配内存(使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 ",vector[i]); } getch(); return 0; } |
此代码将打印所有数组元素,不会发生覆盖。