得到一个field在结构体(struct type)中的偏移量

宏定义:得到一个field在结构体(struct type)中的偏移量

  1. #define OFFSETOF(type, field) ((size_t)&(((type *)0)->field))

  2. (type *)0:把0地址当成type类型的指针。

  3. ((type *)0)->field:对应域的变量。

  4. &((type *)0)->field:取该变量的地址,其实就等于该域相对于0地址的偏移量。

  5. (size_t)&(((type *)0)->field):将该地址(偏移量)转化为size_t型数据。

 为什么是size_t呢?

首先size_t的定义是什么呢,在文件stddef.h中可以找到答案。

  1. typedef unsigned int size_t; /*mine is 32bit machine*/

ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。

 有人这样表达:

  1. #define OFFSETOF(type, field) ((size_t) \
  2.     ((char *)&((type *)0)->field - (char *)(type *)0))

经验证效果是一样的,多增加的那部分就是0地址,相减后就是偏移量。

在嵌入式系统里,不同开发商,不同架构处理器和编译器都有不同的offsetof定义形式:

/* Keil 8051 */

#define offsetof(s,m) (size_t)&(((s *)0)->m)

/* Microsoft x86 */

#define offsetof(s,m) (size_t)(unsigned long)&(((s *)0)->m)

/* Motorola coldfire */

#define offsetof(s,memb) ((size_t)((char *)&((s *)0)->memb-(char *)0))

/* GNU GCC 4.0.2 */

#define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)

/*VC6.0*/

  1. Retrieves the offset of a member from the beginning of its parent structure.

  2. size_t offsetof( structName, memberName );

  3. Routine             Required Header                  Compatibility 
  4. offsetof            <stddef.h>                       ANSI, Win 95, Win NT

offsetof虽然同样适用于union结构,但它不能用于计算位域(bitfield)成员在数据结构中的偏移量。

  1. typedef struct

  2. {

  3.   unsigned int a:3;

  4.   unsigned int b:13;

  5.   unsigned int c:16;

  6. }foo;

使用offset(foo,a)计算a在foo中的偏移量,编译器会报错:error C2104: '&' on bit field ignored



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值