版权声明:本文为博主原创文章,未经博主允许不得转载 https://blog.csdn.net/qq_42719751/article/details/88722102
在提出这几个问题之前,首先应该了解什么是内存对齐?
接下来我们就提出几个问题?
- 如何设置编译器的默认对齐数?
- 如何计算结构体中某变量相对于首地址的偏移量?
解决第一个问题就需要用到指令 #pragma pack ;下面解释一下如何使用它。
1. #pragma pack
#pragma pack 作用:指定结构体、联合以及类成员的packing alignment;
#pragma pack 的语法:
#pragma pack( [show] | [push | pop] [, identifier], n )
#pragma pack( show )//显示当前packing aligment的字节数,以warning message的形式被显示
#pragma pack( push )//将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈
#pragma pack( pop)//从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment数值;如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略
#pragma pack( identifier )//当同push一起使用时,赋予当前被压入栈中的record一个名称;当同pop一起使用时,从internal compiler stack中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作
#pragma pack( n )//指定packing的数值,以字节为单位;缺省数值是8,合法的数值分别是1、2、4、8、16
#pragma pack () //取消自定义字节对齐方式
举个例子
求下面这个结构体的大小
#pragma pack(show)
#include<iostream>
using namespace std;
struct test
{
int a;
char b;
};
int main()
{
struct test t;
cout <<"结构体test的大小为:"<< sizeof(struct test) << endl;
return 0;
}
这个结构体的大小为8(在vs2013下默认对齐数为8);
下面使用 指令 #pragma pack(1) 将默认对齐数修改为1;
#pragma pack(1)
#include<iostream>
using namespace std;
struct test
{
int a;
char b;
};
int main()
{
cout <<"结构体test的大小为:"<< sizeof(struct test) << endl;
return 0;
}
结果为:
#pragma pack()
#include<iostream>
using namespace std;
struct test
{
int a;
char b;
};
int main()
{
cout <<"结构体test的大小为:"<< sizeof(struct test) << endl;
return 0;
}
2.offsetof宏
这个宏的作用就是求结构体中一个成员在该结构体中的偏移量;
使用时要用头文件<stddef.h>;
在MSDN中 该宏这样定义:
size_t offsetof( structName, memberName );
第一个参数是结构体的名字,第二个参数是结构体成员的名字。该宏返回结构体structName中成员memberName的偏移量。偏移量是size_t类型的
举个例子
求下面这个结构体中成员b的偏移量?
struct test
{
double a;
int b;
char c;
};
解法:
#include<stddef.h>
#include<iostream>
using namespace std;
struct test
{
double a;
int b;
char c;
};
int main()
{
cout <<"成员b的偏移量为:"<< offsetof(test,b) << endl;
return 0;
}
结果为:
在Linux中有个相似功能的函数:container_of()函数
但是与offsetof有些不同;
container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址。
在这里对于container_of()函数不做解释。
keep Running