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语言课程基本上指针都不怎么讲,更别说后面的结构体了.这造成很多学生对结构体的不熟悉.这里我就浅谈一下我对结构体的认识. 结构体,就是我们自己定义出一种新的类型,定义好之后, ...
随机推荐
- WebAPI接收JSON参数注意事项
运行环境:ASP.NET 4.5.2. 当我们向GlobalConfiguration.Configuration.MessageHandlers添加一个DelegatingHandler派生类后,很 ...
- c3p0连接数据库的3种方式
c3p0连接数据库的3种方式,这里以mysql为例 1. 直接用set方法设置参数, 基本方法 ComboPooledDataSource dataSource = new ComboPooledDa ...
- 深入Collection集合
List集合 一.ArraryList: 最基本的集合不多做介绍 二.Vector Vector cn=new Vector(); A:有特有功能 a:添加 public void ad ...
- 关于linux下crontab的使用
minute hour day month dayofweek command minute - 从0到59的整数 hour - 从0到23的整数 day - 从1到31的 ...
- JS定时刷新页面及跳转页面
JS定时刷新页面及跳转页面 Javascript 返回上一页1. Javascript 返回上一页 history.go(-1), 返回两个页面: history.go(-2); 2. history ...
- JAVA 问题集中之处以及解决的办法
也许当你看的时候,你可能认为这些都是简单的问题,有什么好记的.其实不是,我认为,我们往往是因为粗心而造成的错误,当你在开发中碰到这些问题时,你能一下看出来是什么错误,达到提高效率.而且往往你把小的问题 ...
- react-echarts之折线图的显示
react中想要实现折线图和饼图的功能,需要引入react-echarts包,然后再实现折线图的功能.我这里引用的版本是:0.1.1.其他的写法参echarts官网即可.下面详细讲解的是我在react ...
- canvas学习之API整理笔记(一)
其实canvas本身很简单,就是去学习它的API,多看实例,多自己动手练习,多总结.但是canvas的API实在是有点多,对于初学者来说,可能学到一半就止步不前了.我也有这种感觉,在学习的过程中,编写 ...
- json简单使用
web工程中如何将大量数据从服务器端传送到浏览器一直是很重要的一个问题. 其中一个解决方法是在服务器端将将数据封装成json格式,然后传给前台.废话不多说,下面讲干货. 1.要用json必须下载一个库 ...
- jQuery选择器笔记
1.$(this).hide() - 隐藏当前元素 $("p").hide() - 隐藏所有段落 $(".test").hide() - 隐藏所有 class= ...