简体   繁体   English

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

[英]malloc for struct with pointer (revisited)

Apologies if this seems like a duplicate question but I'd like some clarification on a previous question I found here regarding allocating heap memory using malloc for a struct containing a pointer. 道歉,如果这似乎是一个重复的问题,但我想澄清一下我在这里找到的关于使用malloc为包含指针的结构分配堆内存的上一个问题 I have found various other questions regarding malloc and structs, but for some reason they all seem to involve people using typedef when defining the struct, I don't know if this changes the context of the question so I want to avoid confusion by asking a new question. 我发现了许多其他有关malloc和struct的问题,但是由于某些原因,它们似乎都涉及在定义struct时使用typedef的人,所以我不知道这是否会改变问题的上下文,因此我想通过询问a来避免混淆新问题。

So the answers to this question seems to imply that with a struct such as: 因此,此问题答案似乎暗示着这样的结构:

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

When creating an instance we should allocate memory space for the struct itself: 创建实例时,我们应该为结构本身分配内存空间:

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

AND the pointer to data inside the struct: AND指向结构内部数据的指针:

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

Problem is I've been reading 'The ANSI C Programming Language' (second edition) by Brian Kernighan and Dannis Ritchie , it's quite an old book but I assumed it was good stuff. 问题是我一直在阅读Brian Kernighan和Dannis Ritchie撰写的“ ANSI C编程语言”(第二版) ,虽然相当老,但是我认为那是一本好书。 Unfortunately it doesn't go into malloc in much detail. 不幸的是,它并没有详细介绍malloc I then came across the following code on page 119 which is illustrating an example of how symbol table management (eg for the preprocessor) might work. 然后,我在第119页遇到了以下代码,该代码说明了符号表管理(例如用于预处理程序)如何工作的示例。 It defines a struct (nlist) for a symbol and the text to replace the symbol with. 它为符号定义了一个结构(nlist),并用该文本替换了该符号。 nlists are stored in a static array (hashtab), using a simple hash function then a modulo array size of the hash to calculate the array index, so there is a pointer to the next nlist if there is a collision: nlists存储在静态数组(hashtab)中,使用简单的哈希函数,然后使用哈希的模数组大小来计算数组索引,因此如果发生冲突,则有一个指向下一个nlist的指针:

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

There is then an install function which is used to add a new nlist to hashtab: 然后有一个安装功能,用于向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;
 }

This is the point at which I started to weep and rock backwards and forwards, drooling as my brain melted out of my ears. 这是我开始哭泣和晃动的点,随着我的大脑从耳朵里融化而流口水。 There doesn't appear to be any malloc action going on for the pointers to next , name or defn in the nlist struct. nlist结构中,指向nextnamedefn的指针似乎没有任何malloc操作。 Is this right or wrong? 这是对还是错?

Thanks. 谢谢。

PS the lookup function is: 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 */
 }

There are several parts to your question: 您的问题分为几个部分:

There doesn't appear to be any malloc action going on for the pointers to next , name or defn in the nlist struct . nlist struct ,指向nextnamedefn的指针似乎没有进行任何malloc操作。 Is this right or wrong? 这是对还是错?

You have seen from the comments that both name and defn have space allocated to hold the associated string by virtue of strdup allocating for you. 从注释中可以看到,借助于strdup为您分配的namedefn都分配了空间来容纳关联的字符串。 (you are therefore on the hook to free both name and defn when they are no longer needed.) (您因此都勾上,以free两个namedefn当他们不再需要。)

The crux of the question, and what seems to be the source of your confusion, is the next pointer for the linked-list. 问题的症结,似乎是您困惑的根源,是链接列表的next指针。 As Ahmad correctly points out, a pointer is a data type, just the same as an int or char . 正如艾哈迈德正确指出的那样, pointer是一种数据类型,与intchar相同。 (the storage size differs depending on the operating system, but generally you will find 4-byte pointers on x86 and 8-byte pointers on x86_64. there are corner-cases with embedded systems, etc.) (存储大小因操作系统而异,但是通常您会在x86上找到4-byte指针,在x86_64上找到8-byte指针。嵌入式系统在某些情况下也会出现这种情况。)

Just as an int can hold an integer and a char can hold a character without further allocation, a pointer can hold a memory address without further allocation. 正如一个int可以容纳一个整数,而char可以容纳一个字符而无需进一步分配一样, pointer可以容纳一个内存地址而无需进一步分配。 If you look at your linked list, specifically, how the next pointer is used, and what the next pointer holds, you will see that next is used to hold nothing but the address of the node that follows: 如果查看链接列表,尤其是next指针的使用方式以及next指针的内容,您将看到, next next指针仅用于保存后面节点的地址:

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

The nodes themselves are allocated: 节点本身已分配:

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

When each node is allocated, space for the next pointer is also allocated. 分配每个节点时,还将分配next指针的空间。 There is no need to further allocate next . 无需进一步分配next It can happily hold the address of the next node all by itself. 它可以很高兴地自己拥有下一个节点的地址。 You only need allocate a block of memory for what is pointed to by the pointer, not the pointer itself. 您只需要为指针指向的内容分配一个内存块,而不是指针本身。

What you are allocating for may be pointers in many cases, for example: 在许多情况下,您要分配的内容可能是指针,例如:

#define NUMPTRS 10

char **list;
list = malloc (NUMPTRS * sizeof *list);

but if you look closely, it follows the rule. 但是如果仔细观察,它就会遵循规则。 You are not allocating space to hold the address of list , you are allocating 10 pointers to hold the address of something else. 您没有分配空间来保存list的地址,而是分配了10指针来保存其他地址。

Hopefully that adds to what Ahmad sought to explain and makes it a little clearer in your mind. 希望这可以增加艾哈迈德想要解释的内容,并使您的头脑更加清晰。 Let me know if you have any questions. 如果您有任何疑问,请告诉我。

footnotes: 脚注:

1. There is no need to cast the return of malloc . 1.无需malloc的返回值。

  np = malloc (sizeof *np); 

is fine by itself. 本身就很好。 see Do I cast the result of malloc? 请参见是否强制转换malloc的结果?

If I have understood your question, here is the answer. 如果我理解您的问题,那么这里就是答案。 (by the way K&R is the best) A pointer holds a memory address, okay? (顺便说一下,K&R最好)指针保存一个内存地址,好吗? when you allocate a, say, int *, or char *, they all allocate the same space in memory to reference respectively an int and a char. 当您分配一个int *或char *时,它们都会在内存中分配相同的空间以分别引用一个int和一个char。 How? 怎么样? In a 32bit system if you take sizeof from both int * and char * you'll find out they have already allocated 4bytes of memory. 在32位系统中,如果您从int *和char *两者中获取sizeof,则将发现它们已经分配了4个字节的内存。 why? 为什么? because they must be big enough to hold the largest address of Ram in a 32bit computer. 因为它们必须足够大以容纳32位计算机中Ram的最大地址。 So if they have already taken a space why would we need to use malloc? 因此,如果他们已经占用了空间,为什么我们需要使用malloc? that's because for a string of size 5 you'll need 6 bytes of memory ( 5 + '\\0' ). 这是因为对于大小为5的字符串,您将需要6个字节的内存(5 +'\\ 0')。 you allocate that memory using malloc then you write down the address of the first byte inside your char *. 您使用malloc分配该内存,然后记下char *中第一个字节的地址。 We won't write it directly inside the char * because those 4bytes are meant to store the address of a string. 我们不会将其直接写入char *内,因为这4个字节用于存储字符串的地址。 right? 对? but let's say you want to just reference another struct in the system(not creating one) then you just put the address of the first byte of the allocated struct inside you struct pointer. 但是,假设您要引用系统中的另一个结构(而不​​创建一个结构),然后将分配的结构的第一个字节的地址放入结构指针中。 Hopefully I've understood your question, otherwise, feel free to comment. 希望我能理解您的问题,否则,请随时发表评论。

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

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