所以,我知道在C中你可以通过引用或值传递函数参数,但从技术上讲,一切都是按值的(因为通过引用传递的实体只是地址)。
我的问题是,如果给出一个不是指针的MEMORY ADDRESS,是否可以对该地址进行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(此时这是一个简单的指针指向包))和修改它的操作是标准指针操作,可以设置包的实际地址的值。这一次,我需要以我上面写的形式提供函数原型,并且它需要能够接收包的地址(不仅仅是指向包的指针)并对该地址进行适当的内存分配操作。关于在目前情况下我能做些什么的任何建议?
答案 0 :(得分:2)
在您的示例中,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));
}
从此函数返回后,您有一个有效的bag
:您已将有效字段填入已存在的结构中,您已通过指针访问该结构。
如果您只传递了结构,那么您将初始化一个本地结构init_bag
。从init_bag
返回后,此结构将丢失,并且调用函数中的bag
将像以前一样未初始化。传递bag
地址的原因是您可以通过指针访问bag
内在调用函数中创建的init_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);
仅限于当前范围。您喜欢哪种变体(或者您是否应该同时使用这两种变体)取决于您想要如何使用该包。
(这里的整个讨论实际上是关于包的内存分配。它不是指桶的内存分配。因为你的struct请求资源,你还应该有一个清理函数来释放这些再次资源。
如果您选择使用malloc在堆上分配包,那么当您清理结构时,当然也必须释放该内存。)