结构体对齐规则
先介紹三個概念:自身對齊值、指定對齊值、有效對齊值。
- 自身對齊值:數據類型本身的對齊值,例如char類型的自身對齊值是1,short類型是2;
- 指定對齊值:編譯器或程序員指定的對齊值,32位單片機的指定對齊值默認是4;
- 有效對齊值:自身對齊值和指定對齊值中較小的那個。
-
存儲模式:
小端:較高的有效字節存儲在較高的存儲器地址,較低的有效字節存儲在較低的存儲器地址。
大端:較高的有效字節存儲在較低的存儲器地址,較低的有效字節存儲在較高的存儲器地址。 -
STM32 屬于小端模式,簡單地說:比如:temp=0X12345678;假設temp的地址為:0X8000 0000
那么,在內存里面,其存儲就變成了:
|? ?? ? 地址? ? ? ? ? ? ? ? ? ? ? ? ? ?|? ? HEX? ? ? ? ? ? ? ? ? ? ? ?|
|0X8000 0000? ? ? ? ? ? ? ? ?? |? ? 78 56 34 12? ? ? ? ? ?|
對齊有兩個規則:
- 1、不但結構體的成員有有效對齊值,結構體本身也有對齊值,這主要是考慮結構體的數組,對于結構體或者類,要將其補齊為其有效對齊值的整數倍。結構體的有效對齊值是其最大數據成員的自身對齊值;
- 2、存放成員的起始地址必須是該成員有效對齊值的整數倍。
- 3、存儲結構如下,其中Y是根據規則1(自身對齊值)補齊的字節,x是規則2(指定對齊值)補齊的字節。
舉四個例子
?
假如結構體起始地址是0x0000,分析結構體:structA
- 成員a的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,占一個字節;
- 成員b的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0001是1的整數倍,故b存放起始地址是0x0001,占一個字節;
- 成員c的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0002是1的整數倍,故c存放起始地址是0x0002,占一個字節;
- 成員d的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0003是1的整數倍,故d存放起始地址是0x0003,占一個字節;
- 此時結構體A的有效對齊值是其最大數據成員的自身對齊值,它的成員都是char類型,故結構體A的有效對齊值是1.
| 0x0000 | 0x00001 | 0x0002 | 0x0003 |
| a | b | c | d |
根據以上規則可以知道其他結構體的存儲結構:
結構體B占6個字節
| 0x0000 | 0x00001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 |
| a | x | b | b | c | d |
?
結構體C占12個字節,分析結構體:structC
- 成員a的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,占一個字節;
- 成員b的自身對齊值4,指定對齊值4,所以有效對齊值是4,地址0x0004是4的整數倍,故b存放起始地址是0x0004,占四個字節;
- 成員c的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0008是1的整數倍,故c存放起始地址是0x0008,占一個字節;
- 成員d的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0009是1的整數倍,故d存放起始地址是0x0009,占一個字節;
- 結構體C的成員占據10個字節,而結構體C的有效對齊值是其成員b的自身對齊值4,10不是4的倍數,故還需補齊兩個字節,此時結構體C占據12個字節,是4的倍數
如下:
| 0x0000 | 0x00001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | 0x0009 | 0x000A | 0x000B |
| a | x | x | x | b | b | b | b | c | d | Y | Y |
結構體D占16個字節,分析結構體:structD
- 成員a的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x0000是1的整數倍,故a存放起始地址是0x0000,占一個字節;
- 成員b的自身對齊值8,指定對齊值4,所以有效對齊值是4,地址0x0004是4的整數倍,故b存放起始地址是0x0004,占八個字節;
- 成員c的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x000C是1的整數倍,故c存放起始地址是0x000C,占一個字節;
- 成員d的自身對齊值1,指定對齊值4,所以有效對齊值是1,地址0x000D是1的整數倍,故d存放起始地址是0x000D,占一個字節;
- 結構體C的成員占據11個字節,而結構體D的有效對齊值是其成員b的自身對齊值8,11不是4的倍數,故還需補齊一個字節,此時結構體C占據16個字節,是8的倍數
如下:
| 0x0000 | 0x00001 | 0x0002 | 0x0003 | 0x0004 | 0x0005 | 0x0006 | 0x0007 | 0x0008 | 0x0009 | 0x000A | 0x000B | 0x000C | 0x000D | 0x000E | 0x000F |
| a | x | x | x | b | b | b | b | b | b | b | b | c | d | Y | Y |
代碼驗證如下:
?
作者: 心飛揚
關于作者:專注于嵌入式,人工智能,請多多賜教!
總結
- 上一篇: STM32 把结构体存入Flash,并读
- 下一篇: 回调函数(运用)