《计算你结构体长度》由会员分享,可在线阅读,更多相关《计算你结构体长度(6页珍藏版)》请在金锄头文库上搜索。
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
3、my_struct char 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
4、_b 是 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 处,之前不需要填
5、充字节;数据成员 b 为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 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
6、 下都相同,例 3 中 double的对齐模数在 Linux 中是 4,在 Windows 下是 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 中较小者,前者
7、为 8 后者为 8,所以结构体对齐模数是 8。sum_b 应该是 8 的整数倍,所以要在结构体后填充 8*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:按照定义,结构体
8、对齐模数是结构体内部最大数据成员长度和 pragma pack 中较小者,前者为 8 后者为 4,所以结构体对齐模数是4。sum_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 处,之前不
9、需要填充字节;数据成员 b 为了内存对齐,根据“结构体大小的计算方法和步骤”中第二条原则,其对齐模数是 4,之前需填充 3 个字节,sum_b = 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; ; s
10、truct my_struct struct my_test a; double my_struct_a; int my_struct_b; char my_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
11、 my_struct_b; char my_struct_c; ;此例子 Windows 中的计算方法如下:步骤 1:所有数据成员自身长度和:4B + 1B + 8B + 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 的整数倍,需在结构
12、体后填充 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 所示。