C - malloc 表示带指针的结构(重新访问)



抱歉,如果这看起来像是一个重复的问题,但我想澄清一下我在这里找到的关于使用 malloc 为包含指针的结构分配堆内存的问题。我发现了有关malloc和结构体的各种其他问题,但是由于某种原因,它们似乎都涉及人们在定义结构时使用typedef,我不知道这是否会改变问题的上下文,所以我想通过提出一个新问题来避免混淆。

因此,这个问题的答案似乎暗示

了这样的结构:
struct Vector {
    double *data;
    size_t size;
};

创建实例时,我们应该为结构本身分配内存空间:

struct Vector *retVal = malloc (sizeof (struct Vector));

和指向结构内数据的指针:

retVal->data = malloc (sz * sizeof (double));

问题是我一直在读Brian Kernighan和Dannis Ritchie的"ANSI C编程语言"(第二版(,这是一本很古老的书,但我认为它是好东西。不幸的是,它没有详细介绍malloc。然后,我在第 119 页上遇到了以下代码,它说明了符号表管理(例如,对于预处理器(如何工作的示例。它为符号定义一个结构 (nlist( 和要用来替换符号的文本。nlist 存储在静态数组 (hashtab( 中,使用简单的哈希函数然后使用哈希的模数组大小来计算数组索引,因此如果发生冲突,则有一个指向下一个 nlist 的指针:

struct nlist { /* table entry: */
     struct nlist *next; /* next entry in chain */
     char *name; /* defined name */
     char *defn; /* replacement text */
 };

然后有一个安装函数,用于将新的nlist添加到hashtab:

struct nlist *lookup(char *);
char *strdup(char *);
/* install: put (name, defn) in hashtab */
 struct nlist *install(char *name, char *defn)
 {
     struct nlist *np;
     unsigned hashval;
     if ((np = lookup(name)) == NULL) { /* not found */
            np = (struct nlist *) malloc(sizeof(*np));
         if (np == NULL || (np->name = strdup(name)) == NULL)
            return NULL;
         hashval = hash(name);
         np->next = hashtab[hashval];
         hashtab[hashval] = np;
     } else /* already there */
        free((void *) np->defn); /*free previous defn */
    if ((np->defn = strdup(defn)) == NULL)
        return NULL;
     return np;
 }

这时,我开始哭泣,前后摇晃,流口水,因为我的大脑从耳朵里融化了。对于指向nlist结构中nextnamedefn的指针,似乎没有任何malloc操作。这是对还是错?

谢谢。

PS 查找函数为:

/* lookup: look for s in hashtab */
 struct nlist *lookup(char *s)
 {
     struct nlist *np;
     for (np = hashtab[hash(s)]; np != NULL; np = np->next)
        if (strcmp(s, np->name) == 0)
            return np; /* found */
     return NULL; /* not found */
 }

您的问题有几个部分:

指针似乎没有任何malloc操作 nextnamedefn nlist struct。这是对的还是 错?

您从注释中看到,namedefn都分配了空间来保存关联的字符串,并且strdup为您分配。(因此,当不再需要namedefn时,您需要free它们。

问题的关键,以及似乎是您困惑的根源,是链表的next指针。正如艾哈迈德正确指出的那样,pointer是一种数据类型,就像intchar一样。(存储大小因操作系统而异,但通常您会在 x86 上找到4-byte指针,在x86_64上找到8-byte指针,嵌入式系统等也有极端情况。

正如int可以保存整数,char可以在不进一步分配的情况下保存字符一样,pointer可以保存内存地址而无需进一步分配。如果您查看链表,特别是如何使用next指针以及next指针保存的内容,您将看到next只用于保存以下节点的地址:

    +----+      +----+      +----+
    |1st |      |2nd |      |3rd |
    |node|  +-->|node|  +-->|node|
    |    |  |   |    |  |   |    |
    |next|--+   |next|--+   |next|-->...
    +----+      +----+      +----+

节点本身分配:

np = (struct nlist *) malloc(sizeof(*np));    [see: footnote 1]

分配每个节点时,还会分配next指针的空间。无需进一步分配next.它可以愉快地独自保存下一个节点的地址。您只需要为指针指向的内容分配一个内存块,而不是指针本身。

在许多情况下,您分配的内容可能是指针,例如:

#define NUMPTRS 10
char **list;
list = malloc (NUMPTRS * sizeof *list);

但如果你仔细观察,它遵循规则。您不是在分配空间来保存list的地址,而是在分配10指针来保存其他东西的地址。

希望这能增加艾哈迈德试图解释的内容,并使你的头脑更清晰一点。如果您有任何问题,请告诉我。

脚注:

1. 没有必要投malloc的回归.

    np = malloc (sizeof *np);

本身就很好。 请参阅我是否投射结果 马洛克?

如果我理解了你的问题,这就是答案。(顺便说一下,K&R是最好的(指针保存一个内存地址,好吗?当你分配一个,比如说,int * 或 char * 时,它们都会在内存中分配相同的空间来分别引用 int 和 char。在 32 位系统中,如果您从 int * 和 char * 中获取 sizeof,您会发现它们已经分配了 4 字节的内存。为什么?因为它们必须足够大才能在 32 位计算机中容纳 Ram 的最大地址。因此,如果他们已经占用了一个空间,为什么我们需要使用 malloc?这是因为对于大小为 5 的字符串,您需要 6 字节的内存 ( 5 + '\0' (。您可以使用 malloc 分配该内存,然后在 char * 中记下第一个字节的地址。我们不会直接将其写入 char * 中,因为这 4 个字节用于存储字符串的地址。右?但是假设你只想引用系统中的另一个结构(而不是创建一个(,那么你只需将分配结构的第一个字节的地址放在你的结构指针中。希望我已经理解了你的问题,否则,请随时发表评论。

相关内容

  • 没有找到相关文章

最新更新