天天看点

经典C语言位域结构体内存对齐

#if   1  

#include <stdio.h>

struct bit_struct

{

char a : 3;

char b : 5;

char c;

char d : 5;

};

struct bit_struct_1

{

char a : 3;

int b : 5;

char c;

short d;

};

struct bit_struct_2

{

int a : 2;

int b : 3;

int c:3;

};

struct bit_struct_3

{

int a : 4;

int b : 5;

int c : 9;

};

int main()

{

struct bit_struct temp;

struct bit_struct_1 temp_1;

struct bit_struct_2 temp_2;

struct bit_struct_3 temp_3;

temp_2.a = 1;

temp_2.b = 7;

temp_2.c = 15;

temp_3.a = 9;

temp_3.b = 0x12;

temp_3.c = 0x10f;

printf("temp_2.a=%x\ntemp_2.b=%x\ntemp_2.c=%x\n", temp_2.a, temp_2.b, temp_2.c);

printf("temp_3.a=%x\ntemp_3.b=%x\ntemp_3.c=%x\n", temp_3.a, temp_3.b, temp_3.c);

char ch[] = { 0xf2, 0xb7, 0xe3 };

char ch_1[] = { 0xf2, 0xb7, 0xe3, 0xf2, 0xb7, 0xe3, 0xf2, 0xb7, 0xe3, 0xf2, 0xb7, 0xe3 };//16

printf("sizeof struct bit_struct=%d\n", sizeof(temp));

printf("sizeof struct bit_struct_1=%d\n", sizeof(temp_1));

memcpy(&temp, ch, sizeof(ch));

memcpy(&temp_1, ch_1, sizeof(ch_1));

printf("temp.a=%x\ntemp.b=%x\ntemp.c=%x\ntemp.d=%x\n", temp.a, temp.b, temp.c, temp.d);

printf("temp_1.a=%x\ntemp_1.b=%x\ntemp_1.c=%x\ntemp_1.d=%x\n", temp_1.a, temp_1.b, temp_1.c, temp_1.d);

return 0;

}

#endif

首先分析一下以上几个结构体的内存空间(以下讨论均以32机为前提)

一、

struct bit_struct

{

char a : 3;

char b : 5;

char c;

char d : 5;

};

bit_struct 结构中占内存最大的成员是char c占1个字节

相同类型的位域编译器会进行压缩存储空间

依据内存1字节对齐得出结构体实际占3个字节

得出如下结构

经典C语言位域结构体内存对齐

经过memcpy后低地址到高地址存储空间的内容为0xf2  0xb7   0xe3

所以再经过符号位扩展(这些数据用printf进行打印的时候是当做%d来解释的,所以会有符号位扩展,后面不再赘述)后temp.a=0x02:(010);temp.b=0xfffffffe:(1 1110);temp.c=0x03(0 0011);

二、

struct bit_struct_1

{

char a : 3;

int b : 5;

char c;

short d;

};

与第一个结构体的区别是位域的类型和一般相邻变量的类型不再一致

编译器对不同类型的相邻位域并不进行压缩存储,但却对不同类型的一般写相邻变量进行压缩存储

最大的类型占4个字节,结构体中不可压缩的部分的存储位置要为4的整数倍

所以结构体占12个字节

经过memcpy后低地址到高地址的内容为0xf2 0xb7 0xe3 0xf2 0xb7 0xe3 0xf2 0xb7 0xe3 0xf2 0xb7 0xe3 

前4个字节的第一个字节的最低位temp_1.a=0x02:(010);中间四个字节的最低位temp_1.b=0x07:(0x1 0111);

temp_1.c=0xffffffe3:(0xe3);temp_1.d=0xffffb7e3;

三、

struct bit_struct_2

{

int a : 2;

int b : 3;

int c:3;

};

最大数据类型int占4字节,struct bit_struct_2占4个字节,根据同类型相邻位域会压缩存储

经典C语言位域结构体内存对齐

temp_2.a=0x01:(001);temp_2.b=0xffffffff:(111);temp_2.c=0xffffffff:(111);

对temp_2.c的赋值虽然超出了其位域的范围但没有超过int类型的取值范围,编译器是从最低位截取进行保存将超出的位数舍弃并没有往高位存储

这个数据结构的成员都没有超过一个字节的,就顺序的存储,如果有某个字再加上一个位域就会存储不下会是什么情况,会另起一个新的字节吗,看下面

四、

struct bit_struct_3

{

int a : 4;

int b : 5;

int c : 9;

};

首先结构体占4个字节没什么疑问

查看内存超过一个字节的编译器也是紧挨着上一个顺序的向高地址存储,结果就不再这里列出了

虽然有些混乱,但是这几个例子基本上把内存对齐和位域结构体的存储细节列出来了

继续阅读