網站首頁 編程語言 正文
結構體的內存對齊
1、計算結構體的大小
struct S1
{
char c1; // 1 byte,默認對齊數為8,所以c1的對齊數是1,第一個成員變量放在與結構體變量偏移量為0的地址處
int i; // 4 byte,默認對齊數為8,所以i的對齊數是4,所以i要放到偏移量為 4的整數倍 的地址處
char c2; // 1 byte,默認對齊數為8,所以c2的對齊數是1,所以c2要放到偏移量為 1的整數倍 的地址處
//最大對齊數是4
//成員大小為9,不是最大對齊數4的整數倍,所以結構體總大小為12
};
printf("%d\n", sizeof(struct S1));
原理分析:
【練習題】
// 練習1
struct S2
{
char c1; // 1 byte / 8,對齊數是1,
char c2; // 1 byte / 8,對齊數是1,
int i; // 4 byte / 8,對齊數是4,
// 最大對齊數是4
// 成員大小為8,是最大對齊數的整數倍,所以結構體總大小為8
};
printf("%d\n", sizeof(struct S2));
// 練習2
struct S3
{
char c; // 1/8,對齊數是1
int i; // 4/8,對齊數是4
double d; // 8/8,對齊數是8
// 最大對齊數是8
// 成員大小為16,是最大對齊數的整數倍,所以結構體總大小為16
};
printf("%d\n", sizeof(struct S3));
// 練習3-結構體嵌套問題
struct S4
{
char c1; // 1/8,對齊數是1
struct S3 s3; // 16 byte,【S3的最大對齊數是8】,所以s3要放到8的整數倍的地址處
double d; // 8/8,對齊數是8
// 最大對齊數是8
// 成員大小為32,是最大對齊數的整數倍,所以結構體總大小為32
};
printf("%d\n", sizeof(struct S4));
2、結構體的對齊規則
第一個成員變量在與結構體變量偏移量為 0 的地址處。
其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
- 對齊數 =「編譯器默認的一個對齊數」與「該成員大小」中的較小值。
- VS中默認對齊數為「8」,Linux中沒有對齊數
結構體總大小為:最大對齊數(每個成員變量都有一個對齊數)的整數倍。
如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。
3、為什么存在內存對齊?
大部分的參考資料是這樣說的:
- 平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特定類型的數據,否則拋出硬件異常。(那我們就要將數據對齊到能夠訪問的這些地址處)
- 性能原因:數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。
4、總結
結構體的內存對齊是拿空間來換取時間的做法。
思考:那在設計結構體的時候,我們既要滿足對齊,又要節省空間,如何做到:
讓占用空間小的成員盡量集中在一起。
// 例如:
struct S1
{
char c1; // 1/8,對齊數是1
int i; // 4/8,對齊數是4
char c2; // 1/8,對齊數是1
// 最大對齊數是4
// 成員大小為9,不是最大對齊數的整數倍,所以結構體總大小為12
};
struct S2
{
char c1; // 1/8,對齊數是1
char c2; // 1/8,對齊數是1
int i; // 4/8,對齊數是4
// 最大對齊數是4
// 成員大小為8,是最大對齊數的整數倍,所以結構體總大小為8
};
S1和S2類型的成員一模一樣,但是S1和S2所占空間的大小卻有了一些區別。
原文鏈接:https://blog.csdn.net/weixin_48025315/article/details/124312688
相關推薦
- 2022-03-15 3 Segmentation fault (core dumped) ./a.out Exited
- 2022-05-08 ASP.NET?MVC視圖尋址_實用技巧
- 2023-12-12 Mybatis中一些優化
- 2022-02-19 DevTools 無法加載 SourceMap 錯誤:狀態代碼 404,net::ERR_HTTP_
- 2022-04-07 React中代碼分割的4種實現方式_React
- 2022-08-17 create-react-app常用自定義配置教程示例_React
- 2022-12-14 C++?Boost?PointerContainer智能指針詳解_C 語言
- 2022-01-17 MongoDB啟動失敗: 此應用無法在你的電腦上運行
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支