结构体成员偏移量的计算
2012-09-04 09:54
267 查看
一、先来一段理论知识
ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。
二、在实践中检验理论
下面是我在window环境下VS2008编译器下的记录,
在上例中,存在两个宏定义,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下,
http://www.jxva.com/blog/201202/335.html,这里有非常详细的说明,大家可以来这里查看。
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,这里有非常详细的说明,大家可以来这里查看。
相关文章推荐
- C语言计算一个结构体内成员地址的偏移量的两种方法(代码实例)
- [C/C++标准库]_[初级]_[计算结构体成员的偏移量]
- [C/C++标准库]_[初级]_[计算结构体成员的偏移量]
- 计算结构体内成员的内存偏移量
- 计算结构体成员地址偏移量...
- ANSI C中获取结构体成员偏移量量的办法
- 计算结构/类中的数据成员的偏移
- 结构体成员的偏移量与offsetof函数
- 从Linux内核代码中学习获得结构体成员偏移量的方法 .
- 用宏来求结构成员偏移量
- 定义一个宏,求出给定结构中给定成员的偏移量
- 通过结构体某个成员的地址计算结构体首地址
- 不能作为非托管结构进行封送处理;无法计算有意义的大小或偏移量
- 结构体成员偏移量,标准C其实有定义宏实现
- c offsetof-计算结构体内成员的偏移值
- 计算结构体成员偏移量
- 如何计算结构体大小和结构体中成员的内存偏移
- 不实例化结构体获取结构体成员在结构体中的偏移量
- 通过宏定义取结构本中成员的偏移量
- 指针直接赋值为整型AND利用宏定义求结构体成员偏移量