遍历存储在堆上的数组

时间:2019-04-15 21:02:51

标签: c arrays pointers memory

请考虑以下代码:

// Thing is a typedef struct
void f(Thing* things, int size) {
    for (int i = 0; i < size; i++) {
        Thing my_thing = things[i];
        my_thing.a = 10;
    }
}

things指向的数组分配在堆上的某个位置。

然而-my_thing是一个“堆栈变量”-在堆栈上分配。

那么幕后发生了什么? things[i]是否已复制到堆栈并存储在my_thing中? my_thing.a = 10;会做什么-它会修改原始的things[i]还是会修改“堆栈副本”?

4 个答案:

答案 0 :(得分:4)

  

事物[i]是否已复制到堆栈中并存储在my_thing中?

是的,作为内存副本,不是深层副本。

  

my_thing.a = 10是什么?会-会修改原始内容[i]还是会修改“堆栈副本”?

它仅修改堆栈副本。但是,在处理指针时要小心,请参见示例here

答案 1 :(得分:2)

    Thing my_thing = things[i];

会将整个结构从事物[i]复制到堆栈上的本地my_thing。复制的数据量将是该结构的大小,因此,如果该结构较大,则可能会有很多数据复制到该结构。

    my_thing.a = 10;

仅影响堆栈上的本地my_thing。原始事物[i]从未修改。如果将const放在输入指针上,代码也将以相同的方式工作,如下所示:

void f(const Thing * things, int size) {
    for (int i = 0; i < size; i++) {
        Thing my_thing = things[i];
        my_thing.a = 10;
    }
}

答案 2 :(得分:1)

my_thingthings[i]是内存中两个不同的对象。线

Thing my_thing = things[i];

创建一个新对象my_thing并将things[i]的内容复制到其中。对my_thing的任何进一步更改(例如my_thing.a = 10;)对things[i]都没有影响,无论是在堆栈还是在堆上分配。

在大多数实现中,“堆栈”和“堆”只是同一内存段中的不同地址范围-它们之间没有真正的区别,只是对那些区域内的对象进行簿记的方式不同。 IOW,将things[i]放在堆上而将my_things放在堆栈上,就复制一个到另一个的机制没关系。

答案 3 :(得分:0)

首先,您是否尝试过此代码是否还能正常工作,因为通常我会写Thing* my_thing = things + i来获取数组中的每个Thing。

为函数提供指向Thing而不是Thing数组的指针。这就是为什么things是第一件事的地址。

要获取下一个,必须将i添加到基本指针中,以获取所需的地址。

下一行的工作方式取决于my_thing是什么类型。

如果它是我声明的指针,它将实际上编辑堆上数组的内容,并且仅在my_thing中创建地址的副本。但是,该行应为(*my_thing).a = 10;,以便您将值实际设置为指针所指向的地址。

如果它是Thing my_thing = *(things + i),则将创建该值的本地副本,下一行将更改该副本,而不是原始数组。

我希望这个答案可以帮助您了解实际情况。