位段
位段:位段是通过结构体来实现的一种以位(bit位)为单位的数据存储结构,它可以把数据以位的形式紧凑的储存,并允许程序员对此结构的位进行操作。位段的成员必须是整型家族的成员(char、int、unsigned int、signed int……)(即基本类型除浮点型)
基本类型位段:
指定数据位段大小
struct packed_data{
unsigned char a : 4;
unsigned int b : 19;
unsigned char c : 3;
unsigned int d : 5;
};
// 输出为4字节, 4+19+3+5<32(位)
对齐(x86下,GCC)
各数据类型位段长度不同,编译器为了提高CPU数据访问速度,规定每次访相问字节大小,所设定的规则每次读取相同字节大小数据,对数据复合数据做的处理叫做对齐。
一般是4个字节(x86下,GCC),高于4字节是4字节的整数倍叫自然对齐,不足4字节的对齐叫做字节对齐,可以根据开发人员需求更改;
数组 :按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。
联合 :按其包含的长度最大的数据类型对齐。
结构体: 结构体中每个数据类型都要对齐。
其中结构体对其最麻烦;
结构体的对齐
先举个例子:
#include <stdio.h>
struct packed_data{
unsigned char a; //char位段1字节
unsigned int b; //int位段4字节
unsigned char c;
unsigned int d;
};
int main()
{
struct packed_data data;
data.a = 6;
data.b = 12;
data.c = 76;
data.d = 45;
printf("%lu\n", sizeof(data)); //打印结构体字节大小
return 0;
}
编译运行得到16字节
编译器是这样处理的
第一个数据char,位段1个字节,第二个int数据,位段是4字节,第二个int数据加入char后超出4字节空间大小,不能使数据对齐,直接存放入下一个空间
举几个例子
struct packed_data{
char a;
char b;
char c;
int d;
};
//结构体占8字节
struct packed_data{
int a;
char b;
char c;
char d;
};
//结构体占8字节
struct packed_data{
long int a;
char b;
short c;
char d;
};
//结构体占8字节
修改对齐规则
1.__attribute__选项
struct stu
{
char sex;
int length;
char name[10];
}__attribute__((aligned (1))); //两个下划线
//指定1字节对齐 注意:(不同编译器环境效果不同)
//我linux GCC 无效果,依然是按4字节对其处理,输出20字节。
//输出无规律,不太实用
struct stu
{
char sex;
int length;
char name[10];
}__attribute__((aligned (8)));
//输出为24 不太实用 可以看下第二种方法
2.#pragma pack(n);指定对齐数(单位:位)
- 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
- 使用伪指令#pragma pack (),取消自定义字节对齐方式。
其中的n就是对齐系数。VS中默认的值为8;linux中的默认值为4。
#pragma pack(2); //指定对其字节数为2字节
struct packed_data{
unsigned char a;
unsigned int b;
char name[10];
unsigned int d;
}data;
data按照指定2字节对齐,输出结果为20;
更深入理解请参考:https://embedx.blog.csdn.net/article/details/108306754