一、字节序
bool am_little_endian ()
{
unsigned short i=1;
return (int)*((char *)(&i)) ? true : false;
}
int main()
{
if(am_little_endian())
{
printf("本机字节序为小段序!\n");
}else
{
printf("本机字节序为大段序!\n");
}
return 0;
}
二、字节对齐
VS默认8,Linux默认4。
结构体字节对齐规则
先介绍三个概念:自身对齐值、指定对齐值、有效对齐值。
a: 自身对齐值:数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2;
b: 指定对齐值:编译器或程序员指定的对齐值,32位单片机的指定对齐值默认是4;
c: 有效对齐值:自身对齐值和指定对齐值较小的那个。
对齐有两个规则:
d: 不但结构体的成员有有效对齐值,结构体本身也有对齐值,这主要是考虑结构体的数组,对于结构体或者类,要将其补齐为其有效对齐值的整数倍。结构体的有效对齐值是其最大数据成员的自身对齐值;
e: 存放成员的起始地址必须是该成员有效对齐值的整数倍。
例子一:
#pragma pack (2)
typedef struct head {
char f
} _head;
#pragma pack ()
int a = sizeof(_head);//a = 1
假如结构体起始地址是0x0000,
成员f的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;
根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员f,体结构体本身对齐值是1。再根据e,1是1的整数倍,所以结构体大小为1。
例子二:
#pragma pack (2)
typedef struct head {
char f
int b;
char c;
} _head;
#pragma pack ()
int a = sizeof(_head);//a = 8
假如结构体起始地址是0x0000
成员f的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e,地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;
成员b的自身对齐值4,指定对齐值2,所以有效对齐值是2,根据规则e,地址0x0002是2的整数倍,故a存放起始地址是0x0002,占4个字节;
成员c的自身对齐值1,指定对齐值2,所以有效对齐值是1,根据规则e,地址0x0006是1的整数倍,故a存放起始地址是0x0006,占一个字节;
此时共用了7个字节,但是根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员b,体结构体本身对齐值是4。再根据e,7不是4的整数倍,所以要+1,,即为8。
例子三:
#pragma pack (16)
typedef struct head {
char f
int b;
char e;
} _head;
#pragma pack ()
_head h;
int a = sizeof(h); //a = 12
假如结构体起始地址是0x0000
成员f的自身对齐值1,指定对齐值16,所以有效对齐值是1,根据 规则e 地址0x0000是1的整数倍,故a存放起始地址是0x0000,占一个字节;
成员b的自身对齐值4,指定对齐值16,所以有效对齐值是4,规则e 地址0x0004是4的整数倍,故a存放起始地址是0x0004,占4个字节;
成员c的自身对齐值1,指定对齐值16,所以有效对齐值是1,规则e 地址0x0008是1的整数倍,故a存放起始地址是0x0008,占一个字节;
此时共用了9个字节,但是根据规则d,体结构体本身也有对齐值,是其最大数据成员的自身对齐值。所以这里是成员b,体结构体本身对齐值是4。再根据e,9不是4的整数倍,所以要+3,,即为12。