C语言结构体对齐
1.结构体变量中的元素如何访问?
(1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式);实质上都是指针方式访问。
(2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来访问。(.和->访问结构体元素其实质是一样的,只是C语言规定用结构体变量来访问元素用. 用结构体变量的指针来访问元素用->。实际上在高级语言中已经不区分了,都用.)
(3)结构体的访问方式有点类似于数组下标的方式
2.利用指针访问结构体元素
结构体元素地址=结构体首地址+元素偏移量
struct mystruct
{
int a;
int b; } s1; //s1.b的地址
int* p=(int*)((int)&s1+);
*p=;// s1.b=5;
3.结构体对齐
一般情况下,为了配合硬件,如果对齐排布和访问会提高效率,否则会大大降低效率。
(0)、一般编辑器默认4字节对齐。
(1)、结构体对齐要考虑:结构体整体本身必须安置在4字节对齐处,结构体对齐后的大小必须4的倍数(编译器设置为4字节对齐时,如果编译器设置为8字节对齐,则这里的4是8)
(2)、结构体中每个元素本身都必须对其存放,而每个元素本身都有自己的对齐规则。
(3)、编译器考虑结构体存放时,以满足以上2点要求的最少内存需要的排布来算。
struct mystruct1
{ // 1字节对齐 4字节对齐
int a; // 4 4
char b; // 1 2(1+1)
short c; // 2 2
}; struct mystruct11
{ // 1字节对齐 4字节对齐
int a; // 4 4
char b; // 1 2(1+1)
short c; // 2 2
}; typedef struct mystruct111
{ // 1字节对齐 4字节对齐 2字节对齐
int a; // 4 4 4
char b; // 1 2(1+1) 2
short c; // 2 2 2
short d; // 2 4(2+2) 2
} My111; typedef struct mystruct2
{ // 1字节对齐 4字节对齐
char a; // 1 4(1+3)
int b; // 4 4
short c; // 2 4(2+2)
}MyS2; struct mystruct21
{ // 1字节对齐 4字节对齐
char a; // 1 4(1+3)
int b; // 4 4
short c; // 2 4(2+2)
} ;
typedef struct myStruct5
{ // 1字节对齐 4字节对齐
int a; // 4 4
struct mystruct1 s1; // 7 8
double b; // 8 8
int c; // 4 4
}MyS5; struct stu
{ // 1字节对齐 4字节对齐
char sex; // 1 4(1+3)
int length; // 4 4
char name[]; // 10 12(10+2)
};
4.结构体对齐指令
以#prgama pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数就是n。
#pragma pack(2) struct s
{
char c; //2 (1+1)
int b; //4 (4) } ;
#pragma pack()
取消对齐访问
__attribute__((packed));
设置结构体整体对齐访问(不包含元素)
__attribute__((aligned(n)));
struct mystruct11
{ // 1字节对齐 4字节对齐
int a; // 4 4
char b; // 1 2(1+1)
short c; // 2 2
}__attribute__((packed)); typedef struct mystruct111
{ // 1字节对齐 4字节对齐 2字节对齐
int a; // 4 4 4
char b; // 1 2(1+1) 2
short c; // 2 2 2
short d; // 2 4(2+2) 2
}__attribute__((aligned())) My111;
5.offsetof宏与container_of宏
offsetof 在0地址处虚拟出一个结构体,通过元素的地址则为偏移量
container_of 通过元素地址减去偏移量得到结构体地址
typeof()传入变量,返回相应的数据类型。
#include<stdio.h> struct mystruct
{
char a;
int b;
short c; };
// TYPE是结构体类型,MEMBER是结构体中一个元素的元素名
// 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int
#define offsetof(TYPE, MEMBER) ((int) &(((TYPE *)0)->MEMBER))//TYPE *为传入值 // ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素的元素名
// 这个宏返回的就是指向整个结构体变量的指针,类型是(type *)
//typeof() 是通过变量名 返回数据类型的
#define container_of(ptr, type, member) ({ \
const typeof(((type *))->member) * __mptr = (ptr); \ //定义一个typeof(((type *)0)->member)类型的指针指向 结构体元素地址
(type *)((char *)__mptr - offsetof(type, member)); }) //元素地址-偏移量=结构体首地址
//通过元素地址减去偏移量得到结构体地址
int main()
{
struct mystruct s1;
struct mystruct *Ps;
s1.b=;
int * pb=&s1.b;
Ps=container_of(pb,struct mystruct,b);
printf("container_of宏实例\n");
printf("&s1=%p\n",&s1);
printf("Ps=%p\n",Ps); //int *p=(int *)((char*)&s1+4);
int *p=(int *)((int)&s1+);
printf("*p=%d.\n",*p);
printf("offsetof宏实例\n");
int offsetof_a=offsetof(struct mystruct,a);
int offsetof_b=offsetof(struct mystruct,b);
int offsetof_c=offsetof(struct mystruct,c);
printf("offsetof_a=%d\n",offsetof_a);
printf("offsetof_b=%d\n",offsetof_b);
printf("offsetof_c=%d\n",offsetof_c); return ; }
C语言结构体对齐的更多相关文章
- 解析C语言结构体对齐(内存对齐问题)
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- 结构体对齐及#pragma详细解释
在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...
- C语言基础--结构体对齐,位域,联合体
结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数 ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- 4-17疑难点 c语言之【结构体对齐】
今天学习了结构体这一章节,了解到了结构体在分配内存的时候采取的是对齐的方式 例如: #include<stdio.h> struct test1 { int a; char b; shor ...
- [置顶]
什么是C语言结构体字节对齐,为什么要对齐?
一.概念 对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的. ...
- C语言结构体的字节对齐原则
为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...
- 漫谈C语言结构体struct、公用体union空间占用
先用代码说话: #include<stdio.h> union union_data0{ int a ;//本身占用4个字节 char b ;//本身占用1个字节 int c ; }; u ...
- 浅谈c语言结构体
对于很多非计算机专业来说,c语言课程基本上指针都不怎么讲,更别说后面的结构体了.这造成很多学生对结构体的不熟悉.这里我就浅谈一下我对结构体的认识. 结构体,就是我们自己定义出一种新的类型,定义好之后, ...
随机推荐
- C#对.zip 存档读取和写入
Framework4.5支持 引用: System.IO.Compression.dll,System.IO.Compression.FileSystem.dll 提取压缩文件 ZipFile.Ext ...
- 在公有云AZURE上部署私有云AZUREPACK以及WEBSITE CLOUD(五)
(五)注册Website Cloud 1 注册Website Cloud 添加Website Cloud 连接Website Cloud 注意, endpoint 是使用Management Se ...
- EF6.0 Code First使用mysql的各种错误和解决办法!!
1.修改或者添加connectionStrings <connectionStrings> <add name="MvcDBContext" connection ...
- python之最强王者(4)——字符串
1.Python 中文编码 前面章节中我们已经学会了如何用 Python 输出 "Hello, World!",英文没有问题,但是如果你输出中文字符"你好,世界" ...
- js判断网页是否加载完毕 包括图片
<script type="text/javascript" language="JavaScript"> //: 判断网页是否加载完成 docum ...
- window下的各种宽高度小结
详细的请打开这里看console.log window.innerWidth: 文档显示区(body)的宽度window.innerHeight 文档显示区(body)的高度window.outr ...
- html5 canvas 详细使用教程
转载自 http://www.cnblogs.com/tim-li/archive/2012/08/06/2580252.html 前言 基本知识 绘制矩形 清除矩形区域 圆弧 路径 绘制线段 绘制贝 ...
- ng-option指令使用记录,设置默认值需要注意
ng-options一般有以下用法: 数组作为数据源: label for value in array select as label for value in array label group ...
- push方法的兼容性问题
在IE8及以下中,不支持aplly方法中的第二个参数是 伪数组 需要对push方法进行封装. 将 push 的判断,放入一个沙箱中: 好处:在页面加载的时候就会执行这段代码,保证了代码只会检测一次 以 ...
- 国外远控软件DarkComet-RAT
下载地址:[点此下载] 使用步骤: 注册noip.org账号创建主机地址. 安装并配置DUC. 配置监听端口 配置NO-IP Updater 然后点击Update ,配置成功则会提示Success. ...