C - 给定地址而不是指针时的内存分配操作

C - Memory Allocation Operations when given ADDRESS, not POINTER

所以,我知道在 C 中您可以通过引用或按值传递函数参数,但从技术上讲,一切都是按值传递的(因为通过引用传递的实体只是地址)。

我的问题是,如果给定一个不是指针的内存地址,是否可以对该地址执行 malloc/calloc 操作?

这是我正在处理的示例:

typedef struct bucket {
    int instances;
    char *key;
    struct bucket *next;
} Bucket;

typedef struct bag {
    int key_count;
    int current_capacity;
    Bucket **buckets;
} Bag;

void init_bag (Bag *bag){...}

在这个 init_bag 函数中,我需要获取在别处声明的 Bag 的地址并对其进行初始化。但是我不知道如果我只得到包的内存地址我会怎么做,如:

Bag bag;
init_bag(&bag);

我以前做过这样的事情,我在 init_bag 函数中取了一个指向包的指针,我在函数参数的曾经被取消引用的实体上使用了 malloc(此时point 是指向包的简单指针),修改它的操作是标准指针操作,可以为包的实际地址设置一个值。不过这一次,我需要有我上面写的形式的函数原型,它需要能够接收包的地址(不仅仅是指向包的指针)并对该地址进行适当的内存分配操作.对我在当前情况下可以做什么有什么建议吗?

在您的示例中,bag 的内存已经分配。当您将其定义为局部变量时:

Bag bag;

您在本地存储中创建了一个结构,其内容未初始化。因此,您的函数 init_bag 不应分配内存,它应该只初始化结构的字段,例如:

void init_bag(Bag *bag) {
    bag->key_count = 0;
    bag->current_capacity = MAX_BAG;
    bag->buckets = calloc(MAX_BAG, sizeof(*bag->buckets));
}

从该函数 return 之后,您有一个有效的 bag:您已将有效字段填充到一个已经存在的结构中,您已通过指针访问该结构。

如果你只传递了结构,你会初始化一个局部于 init_bag 的结构。在从 init_bag 进行 returning 之后,该结构将丢失,并且您在调用函数中的 bag 将像以前一样未初始化。传递 bag 地址的原因是您可以通过指针从 init_bag 中访问在调用函数中创建的 bag 对象。获取对象的地址会创建指向该对象的指针。

另一方面,您在上一段中描述的代码会导致如下结果:

void new_bag(Bag **bag) {
    *bag = malloc(sizeof(**bag);

    (*bag)->key_count = 0;
    (*bag)->current_capacity = MAX_BAG;
    (*bag)->buckets = calloc(MAX_BAG, sizeof(*(*bag)->buckets));
}

你会这样称呼它:

Bag *bag;

new_bag(&bag);

此代码与第一个代码段非常相似,但它做了其他事情。它将像上面一样初始化 Bag 结构,但它会首先在堆上创建 bag 对象。如果您离开当前函数,包仍然有效,而创建的包的生命周期为

Bag bag;

init_bag(&bag);

限于当前范围。您更喜欢哪种变体(或者您是否应该同时实现这两种变体)取决于您希望如何使用包。

(这里讨论的都是bag的内存分配,不是buckets的内存分配,因为你的struct需要资源,所以你也应该有一个clean-up函数,再次释放这些资源。

如果您选择使用 malloc 在堆上分配包,当然,您还必须在清理结构时释放该内存。)