类型大小
32位编译器:32位系统下指针占用4字节
char:1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节)
shortint :2个字节
int: 4个字节
unsigned int: 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器:64位系统下指针占用8字节
char:1个字节
char*(即指针变量): 8个字节
short int :2个字节
int: 4个字节
unsigned int: 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
结构体大小计算方法
① 计算有效对齐值 V = min(n, maxMemberSize);
其中n为指定的编译器选项,即#pragma pack(n)。如果没有指定,gcc在32位系统上默认值是4,在64位系统上默认值是8;
maxMemberSize为结构体中最大的基本类型成员变量的大小;
② 计算offset偏移量 offset = min(V, memberSize);
其中memberSize为当前成员的大小;如果当前成员也是结构体,那么此时memberSize按照该子结构体中最大基本类型成员变量的大小;
③ 结构体的总大小必须为V的整数倍,即totalSize = N*V
实例验证
例1
#include <stdio.h>
struct object {
char a;
};
struct object1 {
char a;
short b;
};
struct object2 {
char a;
int b;
};
int main(void) {
printf("size of struct object is %u\n", sizeof(struct object));
printf("size of struct object1 is %u\n", sizeof(struct object1));
printf("size of struct object2 is %u\n", sizeof(struct object2));
return 0;
}
在32位上和64位上的运行结果分别为:
例2
struct example1 {
short a;
long b;
};
struct example2 {
char c;
struct example1 obj1;
short e;
};
int main(void) {
struct example2 obj2;
printf("size of struct example1 is %u\n", sizeof(struct example1));
printf("size of struct example2 is %u\n", sizeof(struct example2));
unsigned int offset = (unsigned int)(&obj2.obj1) - (unsigned int)(&obj2);
printf("offset is %u\n", offset);
return 0;
}
在32位上和64位上的运行结果分别为:
GCC更改对齐选项
可以通过使用gcc中的__attribute__选项来设置对齐大小。
- _attribute_((packed))
用来让所修饰的结构体在编译的时候不进行对齐优化,按照实际占用的字节数来使用。使用该项修饰后,该结构体后续都不会参与对齐。 - _attribute_((aligned(n)))
让所修饰的结构体成员按照n字节对齐。32位平台上gcc默认按4字节对齐;64位平台gcc默认按照8字节对齐。
代码验证
#include <stdio.h>
#pragma pack(8)
struct example1 {
short a;
long b;
}__attribute__((packed));
//因为example1被__attribute__((packed))修饰了,所以在example2中则不再参与对齐操作
//所以V=min(4, 2) = 2
//offset = min(V, memberSize)
//0 c
//1 obj1
//6 obj1
//7
//8 e
//9 e
//totalSize = 10
struct example2 {
char c;
struct example1 obj1;
short e;
};
#pragma pack()
int main(void) {
struct example2 obj2;
printf("size of struct example1 is %u\n", sizeof(struct example1));
printf("size of struct example2 is %u\n", sizeof(struct example2));
unsigned int offset = (unsigned int)(&obj2.obj1) - (unsigned int)(&obj2);
printf("offset is %u\n", offset);
return 0;
}
在32位平台上运行结果为:
size of struct example1 is 6
size of struct example2 is 10
offset is 1