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 在堆上分配包,当然,您还必须在清理结构时释放该内存。)
所以,我知道在 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 在堆上分配包,当然,您还必须在清理结构时释放该内存。)