经典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]
#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]
相关文章推荐
- Lua和C语言的交互详解
- C#中结构体和字节数组转换实现
- 关于C语言中参数的传值问题
- 简要对比C语言中三个用于退出进程的函数
- 深入C++中API的问题详解
- 基于C语言string函数的详解
- C语言中fchdir()函数和rewinddir()函数的使用详解
- C语言内存对齐实例详解
- 使用C语言判断英文字符大小写的方法
- c语言实现的带通配符匹配算法
- C语言实现顺序表基本操作汇总
- C语言中计算正弦的相关函数总结
- 使用C语言详解霍夫曼树数据结构
- 探讨C语言的那些小秘密之断言
- C语言实现BMP转换JPG的方法
- 深入探讨C语言中局部变量与全局变量在内存中的存放位置
- C语言查找数组里数字重复次数的方法
- C语言泛型编程实例教程
- C语言中使用lex统计文本文件字符数
- 在C语言中转换时间的基本方法介绍