详细解析:如何确定域在结构中的字节偏移的 C语言的代码的实现

     如何确定域在结构中的字节偏移?

ANSI C 在 <stddef.h> 中定义了 offsetof() 宏, 用 offsetof(struct s, f) 可以计算出域 f 在结构 s 中的偏移量。如果出于某种原因, 你需要自己实现这个功能, 可以使用下边这样的代码:

         #define offsetof(type,f) ( (size_t) ( (char*)&((type*)0)->f - (char*)(type*)0) )

    这种实现不是 100% 的可移植; 某些编译器可能会合法地拒绝接受。

    注:上述文字来源于书籍《你必须知道的495个C语言问题》。

    上述代码对于大神来说可能一眼或者两眼就能看懂,但是对于C语言还是像我一样还在懵逼状态的小白来说就同样懵逼,精辟的代码没有解释,让小白们体会不到C语言的强大之处,遍寻(稍微翻了翻)Internet无果后,我决定自己用自己的理解来解释一下,还是不理解的下方评论留言。

    理清问题,要用拆的思想,由局部到整体,由内而外。(装逼的方法论。。。。)

    首先这句话的意思是将

        ( (sie_t) ( (char*)&((type*)0)->f - (char*)(type*)0) )

    用宏定义#define功能实现用

        offsetof(type,f)

    来代替。 也就是我们调用 offsetof(type, f) 就是使用了 ((size_t) ((char *)&((type *)0)->f - (char *)(type *)0)) 这句精妙的语句。实现的功能就是上文所说的可以计算出域 f 在结构 s 中的偏移量(这里偏移量的单位是字节)。我们下面来解释这段代码。

1. (type*)0    //将0强制转换为指向type型结构体的指针,即假装地址0处有一个type的结构
2. (char*)(type*)0)  //将1.处的结构体指针强制转换成字符型指针,这样做的目的是为了使指针(也是一种地址)做减法时得出的偏移量的单位是字节型
3. ((type*)0)->f    //这段代码的结果是得到地址在0处的type结构体的成员f的值地址在0处的type结构体的成员f的值
4. &((type*)0)->f   //在3.的基础上加上了取地址符&,得到的是地址在0处的type结构体的成员f的值的地址地址在0处的type结构体的成员f的值的地址
5. (char*)&((type*)0)->f  //在4.的基础上加上(char*) ,目的同2.处
6. (char*)&((type*)0)->f - (char*)(type*)0)   // 这里其实是上面的5. -2.(结构体成员地址 - 结构体基地址),
                                            //得到的就是我们所求的偏移量(以字节为单位)
7. 在6. 整体上又加了强制类型转换(size_t),目的是为了使结果为无符号整数。 

 

补充一下size_t的来源。

百度百科:

    size_t是标准C库中定义的,应为unsigned int,在64位系统中为 long unsigned int。

 

一个基本的无符号整数的C / C + +类型, 它是sizeof操作符返回的结果类型, 该类型的大小可选择。因此,它可以存储在理论上是可能的任何类型的数组的最大大小。 换句话说,一个指针可以被安全地放进为size_t类型(一个例外是类的函数指针,但是这是一个特殊的情况下)。 size_t类型通常用于循环、数组索引、大小的存储和地址运算。 虽然size_t可以存储一个指针,它的目的是更好地使用另一个unsinged整数类型uintptr_t形式。 在某些情况下,使用size_t类型是更为有效,比习惯性使用无符号类型的程序会更安全。

size_t是在基于无符号整数memsize类型的C / C + +的标准库中定义的。 C语言中,此类型位于头文件stddef.h中,而在C++中,则位于cstddef中。

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值