如果这个似乎像一个重复的问题,我会抱歉,但我想对a previous question I found here有关使用malloc为包含指针的结构分配堆内存的一些说明。我已经找到了关于malloc和structs的各种其他问题,但由于某些原因它们似乎都涉及人们在定义结构时使用typedef,我不知道这是否会改变问题的上下文所以我想避免混淆新问题。
所以answers to this question似乎意味着使用如下的结构:
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;
}
这是我开始哭泣并向后和向前摇晃的时刻,当我的大脑从我的耳朵里融化时流口水。对于malloc
结构中next
,name
或defn
的指针,似乎没有任何nlist
动作。这是对还是错?
感谢。
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 */
}
答案 0 :(得分:2)
您的问题有几个部分:
指针似乎没有任何
malloc
动作next
中的name
,defn
或nlist struct
。这是对还是 错?
您从评论中看到,name
和defn
都有空间分配来保存相关字符串,因为strdup
为您分配。 (因此,当{9}} free
和name
不再需要时,您就会defn
。{/ p>
问题的关键,以及似乎是您混淆的根源,是链接列表的next
指针。正如Ahmad正确指出的那样,pointer
是一种数据类型,与int
或char
相同。 (存储大小因操作系统而异,但一般情况下,您会在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);
答案 1 :(得分:0)
如果我理解了你的问题,这就是答案。 (顺便说一下,K&amp; R是最好的) 指针包含一个内存地址,好吗?当你分配一个,比如说int *或者char *时,它们都在内存中分配相同的空间来分别引用一个int和一个char。怎么样?在32位系统中,如果你从int *和char *中获取sizeof,你会发现它们已经分配了4bytes的内存。为什么?因为它们必须足够大才能在32位计算机中保存Ram的最大地址。所以,如果他们已经占用了空间,为什么我们需要使用malloc?那是因为对于大小为5的字符串,你需要6个字节的内存(5 +'\ 0')。你使用malloc分配那个内存然后你写下你的char *中第一个字节的地址。我们不会直接在char *中编写它,因为这些4bytes用于存储字符串的地址。对?但是,假设您只想引用系统中的另一个结构(而不是创建一个结构),那么您只需将分配结构的第一个字节的地址放在结构指针中。希望我理解你的问题,否则,请随时发表评论。