[英]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
结构中,指向next
, name
或defn
的指针似乎没有任何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
,指向next
,name
或defn
的指针似乎没有进行任何malloc
操作。 这是对还是错?
从注释中可以看到,借助于strdup
为您分配的name
和defn
都分配了空间来容纳关联的字符串。 (您因此都勾上,以free
两个name
和defn
当他们不再需要。)
问题的症结,似乎是您困惑的根源,是链接列表的next
指针。 正如艾哈迈德正确指出的那样, pointer
是一种数据类型,与int
或char
相同。 (存储大小因操作系统而异,但是通常您会在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.