繁体   English   中英

带指针的结构的malloc(已重访)

[英]malloc for struct with pointer (revisited)

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

因此,此问题答案似乎暗示着这样的结构:

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

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

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

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

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

问题是我一直在阅读Brian Kernighan和Dannis Ritchie撰写的“ ANSI C编程语言”(第二版) ,虽然相当老,但是我认为那是一本好书。 不幸的是,它并没有详细介绍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 */
 }

您的问题分为几个部分:

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

从注释中可以看到,借助于strdup为您分配的namedefn都分配了空间来容纳关联的字符串。 (您因此都勾上,以free两个namedefn当他们不再需要。)

问题的症结,似乎是您困惑的根源,是链接列表的next指针。 正如艾哈迈德正确指出的那样, pointer是一种数据类型,与intchar相同。 (存储大小因操作系统而异,但是通常您会在x86上找到4-byte指针,在x86_64上找到8-byte指针。嵌入式系统在某些情况下也会出现这种情况。)

正如一个int可以容纳一个整数,而char可以容纳一个字符而无需进一步分配一样, pointer可以容纳一个内存地址而无需进一步分配。 如果查看链接列表,尤其是next指针的使用方式以及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); 

本身就很好。 请参见是否强制转换malloc的结果?

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM