一:字节对齐
不同操作系统里默认的对其方式存在差别,不过我见过貌似都是8 Byte对齐的,可以通过#pragma pack(n)来设定按n字节对其。
例:
#pragma pack(2) #pragma pack(4)
struct B struct C
{ {
char b; char b;
int a; int a;
short c; short c;
} }
针对上面两个列子,
对于结构体B:
数据成员b自身的对其值为1,指定对其值为2,故有效对其值为1(min(2,1)),假设存放地址为0x0000;
数据成员a自身对其值为4,指定对其值为2,故有效对其值为2(min(2,4)),存放地址的起始地址%2==0,故存放地址应该是:0x0002-0x0005
数据成员c自身对其值为2,指定对其值为2,故有效对其值为2(min(2,2)),存放地址的起始地址%2==0,故存放地址应该是:0x0006-0x0007
总的内存消耗为8。
结构体B自身对其值为4(max(1,2,4)),指定对其值为2,故结构体B有效对其值为2(min(2,4)),总内存消耗8%2==0,不需要补充。
对于结构体C:
数据成员b自身的对其值为1,指定对其值为4,故有效对其值为1(min(4,1)),假设存放地址为0x0000;
数据成员a自身对其值为4,指定对其值为4,故有效对其值为4(min(4,4)),存放地址的起始地址%4==0,故存放地址应该是:0x0004-0x0007
数据成员c自身对其值为2,指定对其值为4,故有效对其值为2(min(2,4)),存放地址的起始地址%2==0,故存放地址应该是:0x0008-0x0009
总的内存消耗为10。
结构体B自身对其值为4(max(1,2,4)),指定对其值为4,故结构体B有效对其值为4(min(4,4)),总内存消耗10%4!=0,需要最少补充2个字节(由此可看出字对齐的弊端——内存浪费,但就换取的效率而言,这还是值得的),故总的内存消耗为12字节。
故:sizeof(B)=8, sizeof(C)=12.
共享体
union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有的数据成员具有相同的起始地址。例子如下:
union StateMachine
{
char character;
int number;
char *str;
double exp;
};
一个union 只配置一个足够大的空间以来容纳最大长度的数据成员,以上例而言,最大长度是double 型态,所以StateMachine 的空间大小就是double 数据类型的大小。
结构体【内存对齐】
结构体变量的所有成员占用不同的存储空间,结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。
#include "stdlib.h"
#include "stdio.h"
//#define NULL 0
//#define LEN sizeof(struct student)//这样就能够求长度,不同于类必须定义对象
//结构体设计到字节对齐,默认是8字节对齐
#pragma pack(8) //按照四字节对齐
struct student1
{ //double a;
int num; // 4字节
char name; //1字节,4
int mark; // 4
}t1; //最大为int型,应为4的倍数
struct student2
{//最大为double,应为8的倍数
double d; //8
char name;//1,8
//short c;
}t2;
//nion数据成员公用一个空间,分配的时候最大的向上取整
union data
{ //为int的倍数
int a,c;
//double d; //8
int i;
char c1;
char c2[9]; //9但是需要4的倍数,就是12
};
int main()
{
printf("s1:%d \n",sizeof(t1));
printf("s1:%d \n",sizeof(t2));
printf("s1:%d \n",sizeof(data));
return 0;
}