/* 結構體(聯合體)對齊規則 */ #include <stdio.h> #include <stdlib.h> #include <string.h> /* * 原則一、第一個數據成員放在offset爲0的地方,之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始(好比int在32位機爲4字節,則要從4的整數倍地址開始存儲)。 * 原則二、結構體做爲成員:若是一個結構裏有某些結構體成員,則結構體成員要從其內部最寬基本類型大小的整數倍地址開始存儲。 *原則三、結構體的總大小爲結構體最寬基本類型成員(成員能夠是基本類型,也能夠是結構體)大小的整數倍,若有須要編譯器會在最末一個成員以後加上填充字節 *最寬基本類型的概念,所謂基本類型是指像char、short、int、float、double這樣的內置數據類型。 */ struct Data1 { int c; char a; char b; }; /* struct Data1分析 分析對齊數 對齊數的值是 結構體中最寬基本類型成員 struct Data1最寬類型是int,佔4個字節大小,因此對齊數的值是4 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性c從offset爲0的位置開始,成員屬性c大小是4個字節,成員屬性c從offset爲0的位置開始存儲,佔據4個字節大小 成員屬性a從offset爲4的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是4,是1的整數倍 因此成員屬性a從offset爲4的位置開始存儲,佔據1個字節大小 成員屬性b從offset爲5的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是5,是1的整數倍 因此成員屬性b從offset爲5的位置開始存儲,佔據1個字節大小 如今struct Data1一共佔據6個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data1最寬基本類型是int,佔4個字節大小 所以結構體的總大小必須是4的倍數,6不是4的倍數,補齊2個字節,變成8個字節 結論:struct Data1 大小是8個字節 */ struct Data2 { char a; int c; char b; }; /* struct Data2分析 分析對齊數 struct Data2最寬類型是int,佔4個字節大小,因此對齊數的值是4 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性a從offset爲0的位置開始,成員屬性a大小是1個字節,成員屬性a從offset爲0的位置開始存儲,佔據1個字節大小 成員屬性c是int類型,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始),如今offset是1,1不是4的整數倍 編譯器填充3個字節,如今offset爲4 , 4是int的整數倍,成員屬性c從offset爲4的位置開始存儲,佔據4個字節大小 成員屬性b從offset爲8的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是8,是1的整數倍 因此成員屬性b從offset爲8的位置開始存儲,佔據1個字節大小 如今struct Data2一共佔據9個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data2最寬基本類型是int,佔4個字節大小 所以結構體的總大小必須是4的倍數,9不是4的倍數,補齊3個字節,變成12個字節 結論:struct Data1 大小是12個字節 */ struct Data3 { char a; short b; double c; }; /* struct Data3分析 分析對齊數 struct Data3最寬類型是double,佔8個字節大小,因此對齊數的值是8 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性a從offset爲0的位置開始,成員屬性a大小是1個字節,成員屬性a從offset爲0的位置開始存儲,佔據1個字節大小 成員屬性b從offset爲1的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是1,不是short的整數倍 編譯器填充1個字節,如今offset爲2 , 2是short的整數倍,成員屬性b從offset爲2的位置開始存儲,佔據2個字節大小 成員屬性c從offset爲4的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是4,不是double的整數倍 編譯器填充4個字節,如今offset爲8 , 8是double的整數倍,成員屬性c從offset爲8的位置開始存儲,佔據8個字節大小 如今struct Data3一共佔據16個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data3最寬基本類型是double,佔8個字節大小 所以結構體的總大小必須是8的倍數,16是8的倍數,不用填充字節 結論:struct Data3 大小是16個字節 */ struct Data4 { short a; char b; double c; char d[5]; }; /* struct Data4分析 分析對齊數 struct Data3最寬類型是double,佔8個字節大小,因此對齊數的值是8 char d[5]並不是基本類型 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性a從offset爲0的位置開始,成員屬性a大小是2個字節,成員屬性a從offset爲0的位置開始存儲,佔據2個字節大小 成員屬性b從offset爲2的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是2,是1的整數倍 成員屬性b從offset爲2的位置開始存儲,佔據1個字節大小 成員屬性c從offset爲3的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是3,不是double的整數倍 編譯器填充5個字節,如今offset爲8 , 8是double的整數倍,成員屬性c從offset爲8的位置開始存儲,佔據8個字節大小 成員屬性d從offset爲16的位置開始,根據原則1(之後每一個數據成員存儲的起始位置要從該成員大小的整數倍開始) ,如今offset是16,是char的整數倍 成員屬性d從offset爲16的位置開始存儲,佔據1個字節大小 如今struct Data4一共佔據17個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data3最寬基本類型是double,佔8個字節大小 所以結構體的總大小必須是8的倍數,17不是8的倍數,須要填充7個字節 結論:struct Data4 大小是24個字節 */ struct Data5 { short a; struct Data4 b; }; /* struct Data5分析 分析對齊數 根據原則2, struct Data4最寬類型是double 佔8個字節大小,而struct Data5成員a佔2個字節,因此對齊數的值是8 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性a從offset爲0的位置開始,成員屬性a大小是2個字節,成員屬性a從offset爲0的位置開始存儲,佔據2個字節大小 成員屬性b從offset爲2的位置開始,根據原則2(結構體成員要從其內部最大元素大小的整數倍地址開始存儲) ,如今offset是2,不是double的整數倍 編譯器填充6個字節,如今offset爲8 , 8是double的整數倍,成員屬性b從offset爲8的位置開始存儲,佔據24個字節大小 如今struct Data5一共佔據32個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data5最寬基本類型是double,佔8個字節大小 所以結構體的總大小必須是8的倍數,32是8的倍數,不須要填充字節 結論:struct Data5 大小是32個字節 */ struct Data6 { double a; struct Data1 b; }; /* struct Data6分析 分析對齊數 根據原則2, struct Data1最寬類型是int 佔4個字節大小,而struct Data5成員a 佔8個字節,因此對齊數的值是8 根據原則1(第一個數據成員放在offset爲0的地方),成員屬性a從offset爲0的位置開始,成員屬性a大小是8個字節,成員屬性a從offset爲0的位置開始存儲,佔據8個字節大小 成員屬性b從offset爲8的位置開始,根據原則2(結構體成員要從其內部最大元素大小的整數倍地址開始存儲) ,如今offset是8 ,是 int 的整數倍 成員屬性b從offset爲8的位置開始存儲,佔據8個字節大小 如今struct Data6一共佔據16個字節大小的空間,根據原則3(必須是其內部最大成員的整數倍),struct Data6最寬基本類型是double,佔8個字節大小 所以結構體的總大小必須是8的倍數,16是8的倍數,不須要填充字節 結論:struct Data6 大小是16個字節 */ void test() { printf("----struct size---1-[%d]------\n", sizeof(struct Data1)); //8 printf("----struct size--2--[%d]------\n", sizeof(struct Data2)); //12 printf("----struct size--3--[%d]------\n", sizeof(struct Data3)); //16 printf("----struct size--4--[%d]------\n", sizeof(struct Data4)); //24 printf("----struct size--5--[%d]------\n", sizeof(struct Data5)); //32 printf("----struct size--6--[%d]------\n", sizeof(struct Data6)); //16 } int main() { test(); printf("-----ok------\n"); getchar(); return 0; }