链表插入值时malloc内存分配的技术疑问
链表插入函数的内存分配与结构体适配问题解答
先看你贴的插入函数代码:
void Insert_val(ListNode **l , int x)//to insert value of x; { ListNode *p ;//create a pointer to datatype ListNode p = malloc(sizeof(ListNode));//give pointer chunk from memory to store data p->val = x;//value of p is x p->next = *l;// next ptr of p points to 1st node *l = p;//head ptr of list points to p making it first node }
问题1:分配的内存如何划分为val和next的存储区域?
首先,sizeof(ListNode)是编译器提前计算好的——它会根据你定义的ListNode结构体的成员类型、声明顺序,算出整个结构体需要的内存大小(还要考虑内存对齐,比如部分编译器要求指针类型成员的地址是4或8字节的倍数,可能会在val和next之间补几个空字节)。
当你用malloc(sizeof(ListNode))申请内存时,系统会分配一块连续的、大小刚好等于这个计算值的内存块。结构体成员在这块内存里的布局是固定的:按照声明顺序排列,第一个成员val从内存块起始地址开始,占用sizeof(int)字节;第二个成员next紧接着val的末尾(如果有对齐补字节则跳过),占用sizeof(ListNode*)字节。
问题2:指针p如何适配ListNode类型的结构?
malloc返回的是void*类型指针,C语言允许void*隐式转换为任意其他指针类型,所以把它赋值给ListNode* p时,编译器会把这个指针标记为「指向ListNode结构体的指针」。
之后你用p->val或p->next访问成员时,编译器其实在帮你计算内存偏移:
p->val等价于*(int*)((char*)p + offsetof(ListNode, val))——从p指向的起始地址,加上val在结构体里的偏移量(这里是0,因为是第一个成员),转换成int指针后取值。p->next则是从p的起始地址,加上val的大小(含对齐补的字节),转换成ListNode*后访问对应内存区域。
本质就是编译器根据结构体定义,自动把内存块的不同区域和结构体成员做了绑定,你不用手动计算偏移,直接用成员名就能访问对应内存。
内容的提问来源于stack exchange,提问作者gunslinger
相关产品推荐
相关产品推荐

