首页 文章

带指针的struct的malloc(重新访问)

提问于
浏览
0

如果这似乎是一个重复的问题,我会抱歉,但是我想对a previous question I found here做一些关于使用malloc为包含指针的结构分配堆内存的说明 . 我发现了关于malloc和structs的各种其他问题,但由于某些原因它们似乎都涉及到在定义结构时使用typedef的人,我不知道这是否会改变问题的上下文所以我想通过询问一个来避免混淆新问题 .

所以answers to this question似乎意味着使用如下的结构:

struct Vector {
    double *data;
    size_t size;
};

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

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

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

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

问题是我一直在阅读 'The ANSI C Programming Language' (second edition) by Brian Kernighan and Dannis Ritchie ,它更详细地进入了 malloc . 然后,我在第119页上看到了以下代码,它说明了符号表管理(例如预处理器)如何工作的示例 . 它定义了符号的结构(nlist)和用符号替换符号的文本 . nlists存储在静态数组(hashtab)中,使用简单的哈希函数,然后使用哈希的模数组大小来计算数组索引,因此如果存在冲突,则会有指向下一个nlist的指针:

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

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

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 */
 }

2 回答

  • 2

    您的问题有几个部分:

    在nlist结构中,似乎没有任何malloc操作用于指向next,name或defn的指针 . 这是对还是错?

    您已从评论中看到 namedefn 已分配空间以通过 strdup 为您分配关联字符串 . (因此,当你不再需要 namedefn 时,你就可以了 . )

    问题的关键,以及似乎是你混淆的根源,是链表的 next 指针 . 正如Ahmad正确指出的那样, 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 指针来保存其他地址 .

    希望这增加了艾哈迈德想要解释的内容,并使你的思想更加清晰 . 如果您有任何疑问,请告诉我 .

    footnotes:

    1.没有必要转换malloc的返回 . np = malloc(sizeof * np);
    本身很好 . 看看我是否施放了malloc的结果?

  • 0

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

相关问题