您的位置:首页 > 编程语言 > C语言/C++

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

2015-10-06 21:00 465 查看
#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机为前提)

一、

[b]struct bit_struct

{
char a : 3;
char b : 5;
char c;
char d : 5;

};

[/b]

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

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

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

[b]得出如下结构[/b]

[b]


[/b]

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

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

[b][b]二、[/b][/b]

[b]struct bit_struct_1

{
char a : 3;
int b : 5;
char c;
short d;

};

[/b]

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

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

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

[b][b]所以结构体占12个字节[/b][/b]

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

[/b]

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

[b]temp_1.c=0xffffffe3:(0xe3);temp_1.d=0xffffb7e3;[/b]

三、

[b]struct bit_struct_2

{
int a : 2;
int b : 3;
int c:3;

};

[/b]

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

[b]


[/b]

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

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

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

四、

[b]struct bit_struct_3

{
int a : 4;
int b : 5;
int c : 9;

};

[/b]

[b]首先结构体占4个字节没什么疑问[/b]

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



[b]虽然有些混乱,但是这几个例子基本上把内存对齐和位域结构体的存储细节列出来了[/b]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息