为了高速处理数据,现代处理器的设计引入了对齐的概念。所谓对齐就是保证数据在内存中存储时地址变化按照必定的规律,这样就能够保证每次cpu取一样长度的数据进行运算,所以能够提升计算机的运行速度。spa
下面的程序演示内存中的对齐:设计
#include <stdio.h> struct test{ char ch; short s; int i; }; int main(void) { struct test var; printf("size of var : %d\n", sizeof(var)); return 0; }
运行结果为:code
该结构体拥有一个char型、一个short型和一个int型成员变量,所占用的字节数应该是7个,可是结果倒是8个字节,这是由于编译器采用了默认的对齐方式。内存
基本数据类型的自身对齐值为其数据类型的大小。编译器
默认的指定对齐值为成员中自身对齐值最大的那个值。io
使用下面语句能够指定对齐值value:编译
#progma pack (value) /*指定按value字节对齐*/ struct A { int a; }; #progma pack () /*取消指定对齐,恢复缺省对齐*/
其成员中自身对齐值最大的那个值。class
自身对齐值和指定对齐值中较小的那个值。test
设结构体以下:变量
struct test{ char ch; int i; short s; };
假设test的起始地址为0x0000,默认的指定对齐值为4,因此:
当咱们指定对齐值为2字节时,再分析上面的结构体
#pragma pack(2) //指定按2字节对齐 struct test1{ char ch; int i; short s; }; #pragma pack() //取消指定对齐,恢复缺省对齐
假设test1的起始地址为0x0000,指定对齐值为2,因此:
1.程序以下:
#include <stdio.h> #pragma pack(8) struct example1 { short a; long b; }; struct example2 { char c; struct example1 struct1; short e; }; #pragma pack() int main(int argc, char* argv[]) { struct example2 struct2; struct example1 e1; printf("size of example1 : %d\n", sizeof(e1)); printf("size of example2 : %d\n", sizeof(struct2)); printf("%d\n", (unsigned long int)(&struct2.struct1) - (unsigned long int)(&struct2)); return 0; }
程序的输出结果是什么?
答案是:
分析这个程序:
对于example1:
对于example2:
对于(unsigned long int)(&struct2.struct1) - (unsigned long int)(&struct2):
由于在example2中struct1以前有个char类型的成员变量,因为struct1的对齐值为8因此char变量须要填充7个字节,所以结果为8。
2.第二个程序:
#include <stdio.h>\ union A { int a[5]; char b; double c; }; struct B { int n; union A a; char c[10]; }; int main(void) { union A a1; struct B b; printf("size of union : %d\n", sizeof(a1)); printf("size of struct : %d\n", sizeof(b)); return 0; }
A和B的大小为:
分析程序:
因为union是共享内存的,首先看每一个成员所占大小:
union A { int a[5]; //20字节 char b; //1字节 double c; //8字节 };
A中各变量默认内存对齐方式,必须以最长的double 8字节对齐,因此A的大小为24字节(20+4)。
结构体B中:
struct B { int n; //4字节 union A a; //24字节 char c[10]; //10字节 };
因为A是8字节对齐的,因此B中的int与char[]也须要8字节对齐,因此大小为:8+24+16 = 48。