0. 前言
A. 嵌套结构体(比如双链表)的初始化一般是什么流程?
B. 嵌套结构体的内存是如何分布的?
C. 结构体中的结构体指针是否需要再次分配内存?不分配会怎么样?
关于嵌套结构体的初始化问题,我找了网上的一些资料,发现能够解决我上述疑问的文章,自己试验后总结一下,欢迎交流。
1. 试验代码:
如下代码实现的功能是这样的:假设有一本空白的本子,你可以使用addPage函数按顺序从第一页开始写入内容,并且可以通过prePage和nextPage查看已经写入的内容。
#include <stdio.h>
#include <stdlib.h>
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;
}
上述代码执行结果:
2. 试验一:
上述代码不做改动的情况下,我们可以得到如下结论:
1). BOOKCreate函数在调用malloc时,已经给head/end/current这些结构体指针分配了地址;
2). 因为结构体内存分配时要遵循对齐原则(详情可参考这篇文章),BOOK和PAGE_INFO结构体都占用了32个字节,符合预期;
3. 试验二:
基于第二小节的第一个结论,我们对上述代码做如下调整,即,注释掉再次给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小节的时延不同的环境打印的结果不同,但是结论一致)。