结构体成员偏移量的计算

        一、先来一段理论知识

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

        二、在实践中检验理论

        下面是我在window环境下VS2008编译器下的记录,

       

#include <stdlib.h>
#include <iostream>
using namespace std;

typedef struct ISO_MSG
{
	char	msg_type[5];
	char	proc_code[7];
}ISO_MSG;

#define fld_sizeof(s, m) sizeof(((s *)0)->m)
//#define offsetof(s,m) (( (size_t) &( ( (s*)0 )->m )) - (size_t)((s*)0))
#define offsetof1(s,m) ( (size_t) &( ( (s*)0 )->m ))

int _tmain(int argc, _TCHAR* argv[])
{
	ISO_MSG sIsoMsg;
	memset((void*)&sIsoMsg,0,sizeof(ISO_MSG));

	strcpy(sIsoMsg.msg_type,"0200");
	strcpy(sIsoMsg.proc_code,"000000");

	cout << fld_sizeof(ISO_MSG,msg_type) << offsetof1(ISO_MSG,msg_type) << endl;
	cout << fld_sizeof(ISO_MSG,proc_code) << offsetof1(ISO_MSG,proc_code) << endl;

	system("pause");
	return 0;
}

         在上例中,存在两个宏定义,fld_sizeof和offsetof;这两个宏定义一个是计算结构成员变量字节大小,一个是计算偏移量,其中offsetof和offsetof1是等价的,

        三、系统的offsetof定义

         该宏在Linux内核代码(版本2.6.22)中定义如下:
         /* Offset of member MEMBER in a struct of type TYPE. */
        #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)


            在windows下,

           

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&reinterpret_cast<const volatile char&>((((s *)0)->m)) )
#else
#define offsetof(s,m)   (size_t)&reinterpret_cast<const volatile char&>((((s *)0)->m))
#endif

#else

#ifdef  _WIN64
#define offsetof(s,m)   (size_t)( (ptrdiff_t)&(((s *)0)->m) )
#else
#define offsetof(s,m)   (size_t)&(((s *)0)->m)
#endif
         四、参考内容

         http://www.jxva.com/blog/201202/335.html,这里有非常详细的说明,大家可以来这里查看。


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值