我可以在不同的函数中访问本地变量吗?如果是这样,怎么样?
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()
函数中复制整个数组才能比第一次更多地访问它?
答案 0 :(得分:56)
myArray
是一个局部变量,因此指针只有在其范围结束时(在这种情况下,包含函数getArray
)才有效。如果以后访问它,则会出现未定义的行为。
实际上,对printf
的调用会覆盖myArray
使用的堆栈部分,然后包含其他一些数据。
要修复代码,您需要在足够长的范围内声明数组(示例中为main
函数),或者在堆上分配它。如果在堆上分配它,则需要手动释放它,或者使用RAII在C ++中释放它。
我错过了一个替代方案(可能是这里最好的一个,只要数组不是太大)就是将数组包装成一个结构,从而使它成为一个值类型。然后返回它会创建一个在函数返回后幸存的副本。有关详细信息,请参阅tp1的answer。
答案 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)
答案 4 :(得分:2)
您的代码调用未定义的行为,因为只要myArray
返回getArray()
超出范围,并且任何尝试使用(取消引用)悬空指针都是UB。
答案 5 :(得分:2)
返回时局部变量超出范围,因此您无法返回指向局部变量的指针。
您需要使用malloc
或new
动态地(在堆上)分配它。例如:
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++)