A. 嵌套结构体(比如双链表)的初始化一般是什么流程?
B. 嵌套结构体的内存是如何分布的?
C. 结构体中的结构体指针是否需要再次分配内存?不分配会怎么样?
关于嵌套结构体的初始化问题,我找了网上的一些资料,发现能够解决我上述疑问的文章,自己试验后总结一下,欢迎交流。
如下代码实现的功能是这样的:假设有一本空白的本子,你可以使用addPage函数按顺序从第一页开始写入内容,并且可以通过prePage和nextPage查看已经写入的内容。
- #include
- #include
-
- typedef struct page_info{
- int index;
- const char *contents;
- struct page_info *pre;
- struct page_info *next;
- }PAGE_INFO;
-
- typedef struct {
- int page_num; // 一本书一共有多少页可以写;
- int count; // 记录当前写了多少页;
- struct page_info *head;
- struct page_info *end;
- struct page_info *current;
- } BOOK;
-
- static BOOK *BOOKCreate(const char *homepage, int page_num)
- {
- BOOK *sys = (BOOK *)malloc(sizeof(BOOK));
- sys->page_num = page_num;
- printf("head address is %x\n",sys->head);
- sys->head = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
- sys->end = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
- sys->current = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
- printf("head address is %x\n",sys->head);
- sys->count = 1;
- sys->head->index = 1;
- sys->head->pre = NULL;
- sys->head->next = NULL;
- sys->head->contents = homepage;
- sys->end = sys->head;
- sys->current = sys->head;
- return sys;
- }
-
- int addPage(BOOK *sys, const char *contents){
- PAGE_INFO *temp = (PAGE_INFO *)malloc(sizeof(PAGE_INFO));
- temp->contents = contents;
- temp->index = sys->current->index + 1;
-
- sys->end->next = temp;
- temp->pre = sys->end;
-
- sys->end = temp;
- sys->count ++;
- return sys->count;
- }
-
- const char *prePage(BOOK *sys)
- {
- if (sys->current->pre != NULL){
- sys->current = sys->current->pre;
- }
- return sys->current->contents;
- }
-
- const char *nextPage(BOOK *sys){
- if (sys->current->next != NULL){
- sys->current = sys->current->next;
- }
- return sys->current->contents;
- }
-
- static void BOOKFree(BOOK *sys)
- {
- free(sys);
- }
-
- int main() {
- printf("size of int is %d\n",sizeof(int));
- printf("size of PAGE_INFO is %d\n",sizeof(PAGE_INFO));
- printf("size of BOOK is %d\n",sizeof(BOOK));
-
- BOOK *sys = BOOKCreate("this is first page.",100);
- printf("%s\n",prePage(sys));
- printf("%d\n",addPage(sys,"this is second page"));
- printf("%s\n",nextPage(sys));
- printf("%s\n",prePage(sys));
- BOOKFree(sys);
- return 0;
- }
上述代码执行结果:
上述代码不做改动的情况下,我们可以得到如下结论:
1). BOOKCreate函数在调用malloc时,已经给head/end/current这些结构体指针分配了地址;
2). 因为结构体内存分配时要遵循对齐原则(详情可参考这篇文章),BOOK和PAGE_INFO结构体都占用了32个字节,符合预期;
基于第二小节的第一个结论,我们对上述代码做如下调整,即,注释掉再次给head/end/current分配堆内存的操作,应该也能正常运行。我们可以看下运行效果:
做上述注释,然后再次运行:
结果:
1. 我们可以看到对sys结构体指针分配内存后,sys->head的内存也已经分配好了,做如上注释后,sys->head的地址没有发生变动;
2. 程序异常退出,不符合预期;
4. 为什么?
我们用IDE debug,单步运行,发现在第一次使用sys->head的时候,程序就已经报错了:
这里我们可以看到sys->head/sys->end/sys->current的地址每次执行都是这个0xbaadf00d,有点奇怪。那这个地址又是什么?
从网上找到了一些资料大家可以参考:地址。资料中提到:
LocalAlloc/GlobalAlloc,如果指定的是LMEM_FIXED(默认就指定了这个),并且没有指定LMEM_ZEROINIT,则分配的内存中初始化值为BAADF00D(可以理解成badfood,也就是不能直接吃的意思,呵呵)。调用LocalFree/GlobalFree则其值会变为FEEEFEEE)可以理解成Free)。
哈哈哈,badfood
到这里我们就很容易得到结论了,结构体使用malloc初始化时,结构体中的指针并没有被分配地址,我们需要通过使用malloc分配内存。(注,第3小节的时延不同的环境打印的结果不同,但是结论一致)。