难以理解指针、动态分配和函数调用行为

Difficulties to understand pointers, dynamic allocation and call to functions behaviour

我在 C 工作

我有一个名为 Entity 的简单结构

typedef struct Entity
{
    int x, y;
    int velX, velY;
}Entity;

我正在创建一个实体类型和大小为 1 的动态数组。然后我使用我的 addEntity 函数添加一个元素

void addEntity(Entity** array, int sizeOfArray)
{
    Entity* temp = malloc((sizeOfArray + 1) * sizeof(Entity));

    memmove(temp, *array, (sizeOfArray)*sizeof(Entity));

    free (*array);
    *array = temp;
}

然后我用另一个函数来改变两个元素的值:

int main()
{
    Entity* entities = malloc(sizeof(Entity)); // dynamic array of size 1

    addEntity(&entities, 1); // add one element
    changeValue(&entities[0], 10); // change the values of the first two elemebts
    changeValue(&entities[1], 20);

    printf("%d\n", entities[0].x); // print the values
    printf("%d", entities[1].x); 

    free(entities); // free the memory

    return 0;
}

void changeValue(Entity* entity, int nb)
{
    entity->x = nb;
}

结果是 10 和 20,一切正常。现在,如果我改用这种语法

int main()
    {
        Entity* entities = malloc(sizeof(Entity)); // dynamic array of size 1
        addEntityAndSetValues(entities);

        printf("%d\n", entities[0].x); // print the values
        printf("%d", entities[1].x); 

        free(entities); // free the memory

        return 0;
    }

void addEntityAndSetValues(Entity* entities)
{
    addEntity(&entities, 1);
    changeValue(&entities[0], 10);
    changeValue(&entities[1], 20);
}

我没有得到 10 和 20,而是一些随机数。我真的不明白为什么。

原因是 C 是按值传递的。

当您在第二种情况下传递指针时 - 它的副本被传递给函数。现在当你写 &entities 它是局部变量的地址。 main 中的变量没有看到任何变化——因为你没有改变它们。所以你得到的是垃圾值。

更清楚

void addEntityAndSetValues(Entity* entities)
{
    addEntity(&entities, 1); <--- entities is a local variable.
}

现在您添加调用 addEntity:

void addEntity(Entity** array, int sizeOfArray)
{
    ...
    free (*array);
    *array = temp; <--- assigning to the local variable the address of the allocated chunk.
}

然后你调用另一个函数来改变它的值 - 这些都可以。但是当你从函数中 return 时,那个局部变量中的所有内容都消失了。

如果你这样做 - 那么它就会起作用。

main()

addEntityAndSetValues(&entities);

addEntityAndSetValues()

void addEntityAndSetValues(Entity** entities)
{
    addEntity(entities, 1);
    changeValue(&(*entities)[0], 10);
    changeValue(&(*entities)[1], 20);
}

在这里它起作用了,因为您已经在 main() 中传递了变量的地址,然后您对该变量进行了更改 - 并且它的值的每个更改都会反映出来。