C语言结构体成员指针差值计算疑问:为何输出为4而非16?
C语言结构体成员指针差值计算疑问:为何输出为4而非16?
嘿,这个问题其实是两个知识点的混淆:结构体的内存对齐+位域规则,还有指针相减的计算逻辑,我来给你掰扯清楚~
首先得纠正你对指针相减的误解:
当两个同类型的指针相减时,得到的结果不是字节数,而是两个指针之间相隔的元素个数。
这里ptr1和ptr2都是unsigned int*类型,每个unsigned int元素占4字节,所以如果两个指针的地址差是16字节,那换算成元素个数就是 16 / 4 = 4——这就是输出4的直接原因。你之前以为会输出16,应该是把指针差值当成了字节数,其实不是哦。
接下来我们拆解结构体的内存布局,看看为什么z的地址和x差16字节:
我们假设结构体的起始地址是0,逐个分析成员的存储:
unsigned int x:占4字节,地址范围是0~3。long int y : 33:这是个位域,它的基础类型是long int(占8字节),而long int的对齐要求是8字节(也就是说这个成员的起始地址必须是8的倍数)。x结束在地址3,所以需要填充4字节(地址4~7),让y的起始地址对齐到8。然后y作为33位的位域,需要一个完整的long int存储单元(8字节,64位)来存放,所以y占用地址8~15,剩下的64-33=31位是空闲的填充位,不会被使用。unsigned int z:它的对齐要求是4字节,此时y结束在地址15,下一个满足4字节对齐的地址是16,所以z从16开始,占用16~19字节。
这样算下来,&t.x的地址是0,&t.z的地址是16,两者的字节差是16,转换成unsigned int*的元素个数就是4,所以printf输出的结果是4。
备注:内容来源于stack exchange,提问作者Ismail Kazdar
相关产品推荐
相关产品推荐

