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语言课程基本上指针都不怎么讲,更别说后面的结构体了.这造成很多学生对结构体的不熟悉.这里我就浅谈一下我对结构体的认识. 结构体,就是我们自己定义出一种新的类型,定义好之后, ...
随机推荐
- 「译」JUnit 5 系列:基础入门
原文地址:http://blog.codefx.org/libraries/junit-5-basics/ 原文日期:25, Feb, 2016 译文首发:Linesh 的博客:JUnit 5 系列: ...
- VS2010 VS2012 VS2013 VS2015启动调试时老是提示正在下载公共符号
VS2010 VS2012 VS2013 VS2015启动调试时老是提示正在下载公共符号,下载一些.dll文件,点取消后也能继续调试,但特别慢.解决方法:工具-选项,或者调试-选项和设置,将调试下的& ...
- C#开发微信门户及应用(3)--文本消息和图文消息的应答
微信应用如火如荼,很多公司都希望搭上信息快车,这个是一个商机,也是一个技术的方向,因此,有空研究下.学习下微信的相关开发,也就成为计划的安排事情之一了.本系列文章希望从一个循序渐进的角度上,全面介绍微 ...
- C# 当前系统的多管理账户测判断
using (DirectoryEntry comp = new DirectoryEntry("WinNT://" + Environment.MachineName + &qu ...
- Delphi_09_Delphi_Object_Pascal_面向对象编程
今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...
- HTML5学习总结——canvas绘制象棋(canvas绘图)
一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...
- Array&String总结
每一部分总结后有实例代码,代码中黄色框方法不改变原数组.PS:所有实例结果均一一运行所得. 符号说明: array和string共享 参数 Array --普通方法 栈: pop() p ...
- iOS之按钮出现时加一个动画效果
//按钮出现时的动画效果 + (void)buttonAnimation:(UIButton *)sender { CAKeyframeAnimation *animation = [CAKeyfra ...
- android 启动模式介绍
Android启动模式 (1)Task:与Android系统是个多任务的系统中的任务是不同的.后者更倾向于多进程和多线程来说的,而这里的任务与application(应用程序)和activity(活动 ...
- JavaScript 事件
事件 概念:事件是可以被 JavaScript 侦测到的行为. JavaScript 使我们有能力创建动态页面.事件是可以被 JavaScript 侦测到的行为. 网页中的每个元素都可以产生某些可以触 ...