我可以访问不同函数中的局部变量吗? 如果是这样,如何?

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()函数中复制整个数组才能比第一次访问它更多?

#1楼 票数:60 已采纳

myArray是一个局部变量,因此该指针仅在其作用域结束(在本例中为包含函数getArray )离开时才有效。 如果稍后访问它,则会出现未定义的行为。

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

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

我错过的另一种选择(甚至可能是这里最好的一种,只要数组不是太大)是将数组包装到结构中,从而使其成为值类型。 然后返回它会创建一个副本,该副本在函数返回后仍然存在。 有关详细信息,请参阅tp1答案

#2楼 票数:19

一旦超出范围,您将无法访问局部变量。 这就是成为局部变量的含义。

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

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

#3楼 票数: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;
}

#4楼 票数:2

一旦离开 getArray,myArray 就会超出范围。 您需要在堆上为它分配空间。

#5楼 票数:2

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

#6楼 票数: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是什么意思,请阅读此问答

#7楼 票数: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(array) 是如何工作的。 C(以及 C++)尽量避免复制数组,而您需要 struct 来超越它。 为什么需要复制是因为作用域——get_array() 函数的作用域消失了,该作用域中仍然需要的每个值都需要复制到调用作用域。

#8楼 票数:1

C++解决方案:

“我可以访问不同函数中的局部变量吗?如果可以,如何访问?”

答案是否定的,不是在函数结束之后。 局部变量在那时被销毁。

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

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

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

#10楼 票数:0

.c 中的静态 ...或全局可以解决问题;)

然而,整个程序将占用这 3 个字节,但您避免在这样的简单事情上执行 malloc(推荐用于大数组的 malloc)

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

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

  ask by Radek Simko translate from so

未解决问题?本站智能推荐:

4回复

函数局部变量的返回如何工作? [复制]

这个问题在这里已经有了答案: 错误:函数返回局部变量的地址8 个回答 什么是 C 中的未定义行为? [重复] (
4回复

从C函数返回局部变量

这个问题已经在这里有了答案: 如何使用指针从其他函数访问局部变量? 9个答案 当我使用gcc -ansi -pedantic -W -Wall进行编译时,编译器会针对foo2()和foo3()发出警告消息: 我以为不允许返回局部变量,但是foo1()可以
4回复

在C ++中指向局部变量的指针[重复]

可能重复: 可以在其范围之外访问局部变量的内存吗? 我在C ++中有以下代码 我得到的输出是: 所以我的问题是因为myVar是一个局部变量,它应该在函数返回后消失吗? 并且它的指针也不应该是空指针吗?
1回复

关于局部变量的意外输出

我在函数foo()创建了一个局部变量b 。 此函数返回变量b的地址。 由于b是一个局部变量的函数foo()该变量的地址不应该在那里作为函数的执行foo()结束。 我收到以下警告消息: 但是main()函数的指针ptr成功接收到b的地址并打印出来。 据我所知,在程序的控制权返回到main()函数之
1回复

局部变量的地址分配给结构中的成员指针

将局部变量分配给成员结构指针。 并最终使其为空。 而不是提供空指针,而是在尝试访问它时给出0。
1回复

返回局部变量的地址[重复]

这个问题在这里已经有了答案: 编译器在返回本地指针时不发出警告(2 个回答) 7 个月前关闭。 '''
2回复

返回局部变量行为的地址[重复]

可能重复: 可以在其范围之外访问局部变量的内存吗? 输入: 输出: 有人可以解释堆栈和操作系统中发生的事情吗? 获取指针值后,为什么结果从13变为垃圾?
1回复

C++ - 指向 Google 练习代码中的局部变量的指针

在这里,在练习 #1 中,有一个函数HardToFollow : 倒数第二行使p指向q ,这是一个局部变量(参数的副本)。 指向局部变量的指针。 稍后,在 main 函数中,作为第一个参数传递的指针在调用后使用。 这不应该是未定义的行为吗? 在调用HardToFollow()之后,作为第一个