目录
Hello everybody!今天我们来聊一聊offsetof相关的知识,我会尽可能的讲得详细一些。
在上一篇文章中我们讲过了宏定义的相关知识以及其中易错的地方。这次我们就围绕宏定义,讲一讲其他的一些看起来比较“高大上”的函数,一来可以帮助大家更好的理解宏定义,二来可以可以拓宽大家的知识面。
希望大家读过这篇文章之后能够有所收获。
1.前言
offsetof经常用于结构体变量中,用于计算结构体中某个成员的地址相对于该结构体起始地址的偏移量。
深入学习过结构体的宝子应该知道结构体中每个成员的地址不一定是连续的,相邻两个成员的地址之间可能会有一些空地址。因此,要计算结构体所占空间的大小就不是单纯的每个成员所占空间大小之和了。
这就涉及到结构体内存对齐相关的知识,在下一期我会详细的讲一下结构体。如果对结构体内存对齐不太了解的话可以先看我的下一篇文章再来学习学习叭\(0^◇^0)/
2.offsetof定义
1.offsetof定义在c语言库文件stddef.h中。
2.offsetof有两个参数,type为类型,member为成员名。
3.offsetof的返回值为size_t :
在64位操作系统下,其含义为long long unsigned int
在32位操作系统下,其含义为unsigned int
3.offsetof用法
offsetof的返回值最好用%zd打印。
打印出32的意思是:假设数组name的首元素地址为0,那么high的地址为32.
打印出40的意思是:假设数组name的首元素地址为0,那么i的地址为40.
由此可见在结构体中,各个成员的地址不一定是连续的,如果是连续的话,这个程序应该打印30而不是32.
4.offsetof宏定义
这段代码与上一段代码不一样的地方就是多了一个宏定义:
1.(type*)0的含义是将0强制类型转换成type*类型的指针,换句话说就是假设该结构体的起始地址为0。这依照offsetof的作用:经常用于结构体变量中,用于计算结构体中某个成员的地址相对于该结构体起始地址的偏移量。
只有假设结构体的起始地址为0,那么其他成员的地址的大小就是相对于该结构体起始地址的偏移量,计算要简单一些。
2.(type*)0->member的含义是用该结构体指针指向其成员名。
3.&(type*)0->member的含义是取该成员的地址。到这里可能有些宝子会有疑问:感觉这里要打括号,不打括号也可以嘛? 注意:指向结构体成员操作符->的优先级是相当高的,要高于取地址操作符&,所以这里可以不打括号。对操作符优先级不太了解的宝子可以看我的上上一期的文章。
4.最后就是(size_t)&(type*)0->member了,(size_t)就是把该结构体成员的地址强转成size_t类型。
5.结语
那么本期关于offsetof的用法及其宏定义的讨论就算结束啦,欢迎大家留言讨论。
这篇文章如有表达不清晰或是逻辑错误的地方欢迎各位技术大佬不吝赐教!