`

[C++] offsetof用法 - 计算成员地址的内存偏移量

    博客分类:
  • C++
 
阅读更多

转自:http://www.cppblog.com/lovedday/archive/2007/09/24/32801.html

offsetof宏解析


今天看代码时,发现一个有用的东东,offsetof(s,m),这是一个宏,MSDN文档的说明如下:

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

size_t offsetof(
structName,
memberName 
);


Parameters

structName 
Name of the parent data structure.


memberName 
Name of the member in the parent data structure for which to determine the offset.


Return Value


offsetof returns the offset in bytes of the specified member from the beginning of its parent data structure. It is undefined for bit fields.
 
Remarks

The offsetof macro returns the offset in bytes of memberName from the beginning of the structure specified by structName. You can specify types with the struct keyword.

Note 


offsetof is not a function and cannot be described using a C prototype.

跟踪代码发现定义如下:

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

然后到网上查了一下,发现还真的是很有用,附带一位大侠的解说:

struct AAA 

    int i; 
    int j; 
}; 

struct AAA *pAAA; 
pAAA=new AAA;


这时,pAAA实际上是一个Pointer, 指向某一确定的内存地址,比如0x1234; 
而 pAAA->i 整体是一个int型变量,其地址是&(pAAA->i) ,'&'为取址运算符; 
那么&(pAAA->i)一定等于0x1234,因为i是结构体AAA的第一个元素。 
而&(pAAA->j)一定是0x1234 + 0x4 = 0x1238; 因为sizeof(int) = 4;

这个做法的巧妙之处就是:它把“0”作为上例中的pAAA,那么 &(pAAA->j)就是j的offset啦。

解析结果是: 
(s *)0 ,将 0 强制转换为Pointer to "s" 
可以记 pS = (s *)0 ,pS是指向s的指针,它的值是0; 
那么pS->m就是m这个元素了,而&(pS->m)就是m的地址,而在本例中就是offset啦 

再把结果强制转换为size_t型的就OK 了,size_t其实也就是int啦!!

也就是说:

0 ---> (s *)0

原来的0是数值类型,现在是结构体指针类型,尽管类型变了,但其值还是不变,也就是说还是0,但这个值的意义变了,现在是地址,而不是数值。

&(((s *)0)->m)求出字段m的地址值,但由于首地址是0,所以&(((s *)0)->m)求出字段m相对于首地址的偏移值。

分享到:
评论

相关推荐

    C语言中结构体偏移及结构体成员变量访问方式的问题讨论

    注:这里的偏移量指的是相对于结构体起始位置的偏移量。 看到这个问题的时候,我相信不同的人脑中浮现的解决方法可能会有所差异,下面我们分析以下几种可能的解法: 方法1 如果你对c语言的库函数比较熟悉的话,那么...

    内存对齐(Memory alignment)

    结构体内存布局2.1 offsetof 定位某成员在结构体中的「 偏移量」2.2 为保证内存对齐,填充了什么值3. 内存对齐3.1 结构体成员默认内存对齐3.2 不同架构内存对齐方式3.3 小试牛刀3.3.1 前置填充3.3.2 中间填充3.3.3 ...

    memoffset:Rust的offsetof

    用于获取结构成员的偏移量。 offset_of_tuple! 用于获取元组成员的偏移量。 (需要Rust 1.20+) span_of! 用于获取一个或多个字段跨度的范围。 memoffset可在no_std环境下no_std 。 用法 将以下依赖项添加到您的...

    对mongoose源码的阅读,写的分享ppt,欢迎一起探讨

    对mongoose源码的分析,另外 分享了一些比较经典的用法,比如函数指针,strcspn实现,offsetof用法等等

    linux内核 0.11版本源码 带中文注释

    \ // 0x70 是写端口号,0x80|addr 是要读取的CMOS 内存地址。 inb_p (0x71); \ // 0x71 是读端口号。 } ) #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) // 将BCD 码转换成数字。 static ...

    深度剖析C语言结构体

    Linux内核的实现博大精深,从offsetof的实现到后面的container_of,为什么通过结构体的的成员就能获得整个结构体的指针呢?这就得益于offsetof宏的实现。关于这个宏,前面的博文也有讲解,但不够深入,今天的这个...

    Go程序设计语言

    简介 本书由《C程序设计语言》的作者Kernighan和...27613.1 unsafe.Sizeof、Alig[0no0]f 和Offsetof 27613.2 unsafe.Pointer 27813.3 示例:深度相等 28013.4 使用cgo调用C代码 28213.5 关于安全的注意事项 286

    《C深度解析》第7、8章 结构体/共用体/枚举,杂项(自动类型转换、大小端序等)

    结构体结构体定义、访问、传参,结构体对齐(offsetof宏、contaner_of宏),结构体内嵌函数指针,程序分层,模块化等。2. 共用体共用体与结构体的异同、共用体的作用、共用体举例3. 枚举第8章:自动类型转换、大小...

Global site tag (gtag.js) - Google Analytics