C 语言结构体及位域内存大小
小白一枚,最近线学习野火stm32,写个博客记录下自己学习之路。
以下资料来自野火论坛以及其他网站。
存对齐的规则很简单:
1.起始地址为该变量类型所占内存的整数倍,若不足则不足部分用数据填充至所占内存的整数倍。
2.该结构体所占总内存为结构体成员变量中最大数据类型的整数倍。
一.看如下例子:(假设char 是 1个字节,double是8个字节,int是2个字节 ,float4字节)
typedef struct
{
char a;
double b;
}test;
求sizeof(test)的值?
答案:1+7 +8 = 16;
typedef struct
{
char a;
double b;
int c;
}test;
求sizeof(test)的值?
答案:1+7+8+4+4=24;(最后还加了4是因为总长度是8的整数倍,所以补齐+4);
当结构体中的变量的位置变化时,其结果也会不一样哦~
typedef struct
{
double b;
char a;
int c;
}test;
答案是:8+1+3+4=16;
再看下一个,当存在: #pragma pack(4)
#pragma pack(4) //规定以4字节对齐
typedef struct
{
char a;
double b;
int c;
}test;
求sizeof(test)的值?
答案:1+3+8+4=16;
现在再插个联合体试试 = =
struct stu
{
union{
char bj[5];
int bh[2];
}class;
char xm[8];
float cj;
}xc;
//则 sizeof(xc)的值为?
答案:联合体占用5字节 但是对齐方式int(2字节),所以再加1,为6;接着6+8位14字节,为了对齐float的4字节,这里补充2字节,最后的结果是:5+1+8+2+4=20;
现在再进一步看看:
struct stu
{
union{
char bj[5];
int bh[2];
}class;
char xm[8];
float cj;
}xc;
//若 xc 地址为0x1000 则求 &xm[0] 的值?
答案:0x1000+6=0x1006;
二.位域
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的 sizeof 大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止*
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的 sizeof 大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6 采取不压缩方式,Dev-C++采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
例子:
struct test
{
char f1 : 3;
short f2 : 4;
char f3 : 5;
};
求 sizeof(test)大小?
这个好像比较简单:3+4,占了7位了,再来个5的话,一个字节就塞不住了,所以f3存入下一个字节,总的也就是2字节。
当存在非位域的字段时,则不会进行压缩。
struct C{
char f1 : 3;
char f2;
char f3 : 5;
};
求 sizeof(test)大小
答案:1+1+1=3;
所以一般情况下占用空间小的类型排在前面,占用空间大的类型排在后面,这样可以相对节约一些对齐空间 。
*第一次写,不足之处还请指正~~~~*