1、计算你结构体长度计算结构体长度:http:/ 结构体总长度2 结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置结构体大小的计算方法和步骤1 将结构体内所有数据成员的长度值相加,记为 sum_a; 2 将各数据成员为了内存对齐,按各自对齐模数而填充的字节数累加到和 sum_a上,记为 sum_b。对齐模数是#pragma pack 指定的数值以及该数据成员自身长度中数值较小者。该数据相对起始位置应该是对齐模式的整数倍。 3 将和 sum_b向结构体模数对齐,该模数是#pragma pac 指定的数值和结构体内部最大的基本数据类型成员长度中数值较小者。结构体的长度应该是该模数的整数倍
2、。结构体大小计算举例在计算之前,我们首先需要明确的是各个数据成员的对齐模数,对齐模数和数据成员本身的长度以及 pragma pack编译参数有关,其值是二者中最小数。如果程序没有明确指出,就需要知道编译器默认的对齐模数值。下表是 Windows XP/DEV-C+和 Linux/GCC中基本数据类型的长度和默认对齐模数char short int long double long double Windows 长度 1 2 4 4 8 12 模数 1 2 4 4 8 4 Linux 长度 1 2 4 4 8 12 模数 1 2 4 4 4 4 例子 1: struct my_struct ch
3、ar a; long double b; ;此例子 Windows和 Linux计算方法一样,如下:步骤 1:所有数据成员自身长度和:1B + 12B = 13B,sum_a = 13B步骤 2:数据成员 a放在相对偏移 0处,之前不需要填充字节;数据成员 b为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 4,之前需填充 3个字节,sum_b = sum_a + 3 = 16B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 12后者为 4,所以结构体对齐模数是4。sum_b 是 4的 4倍,不需再次对齐。综上
4、 3步,可知结构体的长度是 16B,各数据成员在内存中的分布如图 1所示。例子 2: #pragma pack(2) struct my_struct char a; long double b; ; #pragma pack()例子 1和例子 2不同之处在于例子 2中使用了#pragma pack(2)编译参数,它强制指定对齐模数是 2。此例子 Windows和 Linux计算方法一样,如下:步骤 1:所有数据成员自身长度和:1B + 12B = 13B,sum_a = 13B步骤 2:数据成员 a放在相对偏移 0处,之前不需要填充字节;数据成员 b为了内存对齐,根据“结构体大小的计算方法和
5、步骤”中第二条原则,其对齐模数是 2,之前需填充 1个字节,sum_b = sum_a + 1 = 14B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragmapack中较小者,前者为 12后者为 2,所以结构体对齐模数是2。sum_b 是 2的 7倍,不需再次对齐。综上 3步,可知结构体的长度是 14B,各数据成员在内存中的分布如图 2所示。例子 3: struct my_struct char a; double b; char c; ;前两例中,数据成员在 Linux和 Windows下都相同,例 3中 double的对齐模数在 Linux中是 4,在 Windo
6、ws下是 8,针对这种模数不相同的情况加以分析。在 Windows中计算步骤如下:步骤 1:所有数据成员自身长度和:1B + 8B + 1B = 10B,sum_a = 10B步骤 2:数据成员 a放在相对偏移 0处,之前不需要填充字节;数据成员 b为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 8,之前需填充 7个字节,sum_b = sum_a + 7 = 17B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 8后者为 8,所以结构体对齐模数是 8。sum_b 应该是 8的整数倍,所以要在结构体后填充 8
7、*3 - 17 = 7个字节。综上 3步,可知结构体的长度是 24B,各数据成员在内存中的分布如图 3所示。在 Linux中计算步骤如下:步骤 1:所有数据成员自身长度和:1B + 8B + 1B = 10B,sum_a = 10B步骤 2:数据成员 a放在相对偏移 0处,之前不需要填充字节;数据成员 b为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 4,之前需填充 3个字节,sum_b = sum_a + 3 = 13B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 8后者为 4,所以结构体对齐模数是4。s
8、um_b 应该是 4的整数倍,所以要在结构体后填充 4*4 - 13 = 3个字节。综上 3步,可知结构体的长度是 16B,各数据成员在内存中的分布如图 4所示。例子 4: struct my_struct char a11; int b; char c; ;此例子 Windows和 Linux计算方法一样,如下:步骤 1:所有数据成员自身长度和:11B + 4B + 1B = 16B,sum_a = 16B步骤 2:数据成员 a放在相对偏移 0处,之前不需要填充字节;数据成员 b为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 4,之前需填充 3个字节,sum_b
9、= sum_a + 3 = 19B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 4后者为 4,所以结构体对齐模数是 4。sum_b 是 4的整数倍,需在结构体后填充 4*5 - 19 = 1个字节。综上 3步,可知结构体的长度是 20B,各数据成员在内存中的分布如图 5所示。例子 5: struct my_test int my_test_a; char my_test_b; ; struct my_struct struct my_test a; double my_struct_a; int my_struct_b; char m
10、y_struct_c; ;例子 5和前几个例子均不同,在此例子中我们要计算 struct my_struct的大小,而 my_struct中嵌套了一个 my_test结构体。这种结构体应该如何计算呢?原则是将 my_test在 my_struct中先展开,然后再计算,即是展开成如下结构体: struct my_struct int my_test_a; char my_test_b; double my_struct_a; int my_struct_b; char my_struct_c; ;此例子 Windows中的计算方法如下:步骤 1:所有数据成员自身长度和:4B + 1B + 8B
11、+ 4B + 1B= 18B,sum_a = 18B步骤 2:数据成员 my_struct_a为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 8,之前需填充3个字节,sum_b = sum_a + 3 = 21B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 8后者为 8,所以结构体对齐模数是 8。sum_b 是 8的整数倍,需在结构体后填充 3*8 - 21 = 3个字节。综上 3步,可知结构体的长度是 24B,各数据成员在内存中的分布如图 6所示。此例子 Linux中的计算方法如下:步骤 1:所有数据成员自身长度和:4B + 1B + 8B + 4B + 1B= 18B,sum_a = 18B步骤 2:数据成员 my_struct_a为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 4,之前需填充3个字节,sum_b = sum_a + 3 = 21B步骤 3:按照定义,结构体对齐模数是结构体内部最大数据成员长度和 pragma pack中较小者,前者为 4后者为 4,所以结构体对齐模数是4。sum_b 是 4的整数倍,需在结构体后填充 6*4 - 21 = 3个字节。综上 3步,可知结构体的长度是 24B,各数据成员在内存中的分布如图 6所示。