【问题标题】:C - Memory Allocation Operations when given ADDRESS, not POINTERC - 给定地址时的内存分配操作,而不是指针
【发布时间】:2015-05-04 06:38:52
【问题描述】:

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

我的问题是,如果给定一个不是指针的内存地址,是否可以对该地址执行 m​​alloc/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 bag;
init_bag(&bag);

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

【问题讨论】:

  • 欢迎来到 Stack Overflow。如果您还没有这样做,请阅读About 页面。我很困惑:一个内存地址是一个指针,而一个指针是一个内存地址(嗯,在大多数情况下这是准确的)——你试图做出什么区分并不是很明显。在bag_init() 内部,您使用bag->key_count = 0; 将密钥计数设置为0,等等。或者,如果您不正常,您可以编写(*bag).key_count = 0;,但您的代码可读性会降低,这是一件坏事。您确定需要为 Bag 中的 buckets 元素添加双指针吗?
  • 内存地址不是指针,而是使用指针数据类型存储的。
  • 您指的是什么“malloc/calloc 操作”。 这些函数都没有将指针作为参数。你想到了什么样的“操作”?您的 Bag 示例看起来与它应该的完全一样。您将Bag 对象的地址作为值传递给一个函数,该函数具有指向相同类型(Bag) 的指针,该指针声明为接收所述地址的形式参数。那么问题出在哪里?

标签: c pointers dynamic-memory-allocation memory-address


【解决方案1】:

在您的示例中,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 地址的原因是您可以通过指针从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);

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

Bag bag;

init_bag(&bag);

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

(这里的整个讨论实际上是关于为bag分配内存。它不是指为bucket分配内存。因为你的结构请求资源,你还应该有一个清理函数来释放这些再次资源。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多