首页 > 编程知识 正文

向宏,Offset函数

时间:2023-05-03 17:31:19 阅读:115941 作者:3131

定义宏: c语言面试可能会通过:

#defineoffsetof(type,MEMBER ) ) size_t ) ) TYPE* )0)-MEMBER )函数作用:计算结构成员的偏移。 有些代码上也会手写这样的代码。 实际上,如果您查看ANSI C编译器的头文件,就会在stddef.h中遇到这样奇怪的宏。 这个红色有可怕的声明。 另外,参照编译器手册,有以下无益的说明。

offsetof ) )宏返回结构或组合中元素名称的偏移。 这提供了一种确定偏移的可移植方法。

函数的声明是这样的

size_toffsetof(type,member );函数描述:

offset宏返回字段成员从结构类型开头的偏移。

此宏很有用,因为组成结构的字段的大小取决于实现,编译器可能会在字段之间插入不同数量的填充字节。 因此,元素的偏移量不一定由前面的元素的大小之和给出。

如果成员与字节边界不对齐,例如,如果成员是位字段,则会发生编译器错误。

返回值:

返回指定类型的指定成员的偏移(以字节为单位)

标准:C89, C99, POSIX.1-2001

源代码:

# includeiostreamusingnamespacestd; int main () structdemo ) inta; char b; 双精度c; char d[]; (;/* outputiscompilerdependent */printf (sizeof (结构演示) %LD(n ),(long ) sizeof (结构演示) ); printf(offsets:a=%LD; b=%ld; c=%ld d=%ldn ',long(offsetof(structdemo,a ),long (offset of ) offset of (structdemo,b ) ) long (offset of ) struct demo }输出结果:

sizeof (结构演示)=16offsets: a=0; b=4; c=8 d=16了解这个机制后,看看他在做什么。

offset的工作原理:

offset宏的偏移是ANSI要求的宏,必须在stddef.h中找到。 也就是说,offset宏返回结构或合并的特定元素之前的偏移字节数。

宏声明因供应商而异,也因处理器体系结构而异。

我浏览了各种编译器,找到了清单的示例声明。

//keil 8051 compiler # define offset of (s,m ) ) (s * )0)-m )/Microsoftx86compiler ) (版本7 ) defined _ CRT _ use _ builtin _ offset of # ifdef _ _ cplusplus # define offset of (s, m () :size_t ) reinterpret _ castcharconstvolatile (() (s* )0)-m ) ) else#defineofsetof m ) _builtin_offsetof,m ) ) #endife,m ) ) endin 1第一个参数是结构名称;第二个参数是结构元素的名称。

为了更好地理解offset宏的魔力,让我们来详细了解定义。 宏中的各种运算符按顺序计算,并执行以下步骤:

(s * )0) :取整数零,将其转换为指向s的指针。 (s * )0)-m:引用指向结构成员m的指针。 () ) s * )0(-m ) :计算m的地址。 (size_t ) ((s * )0)-m ) :将结果转换为相应的数据类型。 根据定义,结构本身位于地址0。 因此,指示字段(上述步骤3 )的地址必须是距结构体的开头的偏移量(以字节为单位)

在结构体中嵌入结构体时:

//Sytax.cpp :此文件包含“main”函数。 程序的执行在此开始和结束。 //# includeiostreamusingnamespacestd; int main () structdemo ) inta; char b; 双精度c; char d[]; (; 类型结构{ long l; 短整型; } SBAR; 类型结构{ int I; 浮动f; SBAR b; } SFOO;/* outputiscompilerdependent */printf (' offset of ' l ' is % un ',offsetof(sfoo,b.l ) ); printf (sizeof (结构演示) %LD(n ),(long ) sizeof (结构演示) ); printf(offsets:a=%LD; b=%ld; c=%ld d=%ldn ',long(offsetof(structdemo,a ),long (offset of ) offset of (structdemo,b ) ) long (offset of ) struct demo } 知识点:结构填充字节

大多数16位或更高的处理器都需要在多个字节(例如16位或32位)的边界上对齐内存中的数据结构。 要求可能是绝对的,也可能只是为了获得最佳的总线吞吐量而推荐。 在后者的情况下,之所以提供灵活性,是因为设计者可能希望将内存访问时间与其他冲突问题(如内存大小和传输能力(例如通信链路和直接内存访问) )进行权衡。 内存内容直接发送到具有不同对准要求的另一个处理器。

还有一个相关的宏:

7 //从“结构(type )变量”中的“指向域成员变量(member )的指针(ptr )”指向整个结构变量的指针8 # define container _ of (ptr,type,MMP ) } )扩展:

常用编译器以8字节对齐。 更改对齐字节后,偏移会发生变化

#pragmapack(push ) /将当前pack设置保存到堆栈(pragmapack )2)//在结构定义之前输入结构演示{ int a; //4,Offset 0通道b; //1,Offset 4双精度c; //8,offset 6char d[]; //1,offset 14}; #pragmapack(pop )//恢复以前的pack设置的输出结果:

sizeof (结构演示)=14offsets: a=0; b=4; c=6 d=14

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。