内存对齐和大小端
一、内存对齐的原因
根本原因:cpu是根据内存访问粒度(memory access granularity,下文简写成MAG)来读取内存,MAG就是cpu一次内存访问操作的数据量,具体数值依赖于特定的平台,一般是2byte、4byte、8byte。
内存对齐:更够减少内存读取次数(相对于内存不对齐),为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
二、内存对齐的步骤
每个平台上的编译器都有自己的默认“对齐系数”。同时,我们也可以通过预编译命令#pragma pack(n)...#pragma pack()来改变对齐系数n,取值为1字节,2字节,4字节,8字节,16字节。
当结构体进行内存分配时,分两步对齐:
第一、每个结构体成员所分配的存储位置与起始点的偏移量必须能够整除min(对齐系数,成员字节数),这一步可以称为成员对齐;
第二、整个结构体所占存储空间要能整除min(max(成员字节数),对齐系数),这一步可以称为结构体对齐。
注:由于平常的vc系统默认的pack(8),已经是类型最大的longlong的字节数,所以通常内存对齐都是自然对齐方式。
三:大小端的问题和union联合体
- 大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
- 小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
union联合体特点:所有成员的起始地址一致。
同时:也会根据最新表示的类型覆盖原来的字节的值
union
{
int i;
char a[2];
}*p, u;
p =&u;
p->a[0] = 0x39;
p->a[1] = 0x38;
union 型数据所占的空间等于其最大的成员所占的空间。对union 型的成员的存取都是相对于该联合体基地址的偏移量为0 处开始,也就是联合体的访问不论对哪个变量的存取都是从union 的首地址位置开始。如此一解释,上面的问题是否已经有了答案呢?
int checkSystem( )
{
union check
{
int i;
char ch;
} c;
c.i = 1;
return (c.ch ==1);
}