網站首頁 編程語言 正文
1. 默認字節對齊
- 在所有結構體成員的字節長度都沒有超出操作系統基本字節單位(32位操作系統是4,64位操作系統是8)的情況下
按照結構體中字節最大的變量長度來對齊; - 若結構體中某個變量字節超出操作系統基本字節單位
那么就按照系統字節單位來對齊。
注意:
并不是32位就直接按照4個字節對齊,64位就按照8個字節對齊。
2. 為什么存在字節對齊
2.1 了解 CPU 一次讀取內存數
CPU 一次能讀取多少內存要看數據總線是多少位
- 如果是16位,則一次只能讀取 2 個字節
- 如果是32位,則可以讀取 4 個字節,并且
CPU 不能跨內存區間訪問
。
例子:
假設有這樣一個結構體如下:
struct st3
{
char a;
int b;
};
//在32位系統下,它就應該是8個字節的。
假設地址空間是類似下面這樣的:
-
在沒有字節對齊的情況下,
- 變量 a 就是占用了 0x00000001 這一個字節,而變量b則是占用了 0x00000002~0x000000005 這四個字節
- 此時 cpu 如果想從內存中讀取變量 b,首先要從變量 b 的開始地址 0x00000002讀到 0x0000004,然后再讀取一次 0x00000005 這個字節,相當于讀一個 int,cpu 從內存讀取了兩次。
-
如果進行字節對齊的話
- 變量 a 還是占用了 0x00000001 這一個字節,而變量 b 則是占用了 0x00000005~0x00000008 這四個字節
- 此時 cpu 要讀取變量 b 的話,就直接一次性從 0x00000005 讀到 0x00000008 ,就一次全部讀取出來了。
總結:
-
字節對齊的根本原因其實在于 cpu 讀取內存的效率問題
,對齊以后,cpu讀取內存的效率會更快。 - 對齊的時候 0x00000002~0x00000004 這三個字節是浪費的,所以字節對齊實際上也有那么點以空間換時間的意思,具體寫代碼的時候怎么選擇,其實是看個人的。
3. 編碼時手動設置對齊
兩種。
3.1 代碼里添加預編譯標識 pragma pack(n)
3.1.1 用法
- 使用預編譯指令 #pragma pack (n) 來告訴編譯器,使用我們指定的對齊值來取代缺省的。
- 對齊的算法: 隨編譯器變化
//用法如下
#pragma pack(n)//表示它后面的代碼都按照n個字節對齊
struct st3
{
char a;
int b;
};
#pragma pack()//取消按照n個字節對齊,是對#pragma pack(n)的一個反向操作
3.1.2 例子
#include <stdio.h>
#pragma pack(1)//表示它后面的代碼都按照n個字節對齊
struct st3
{
char a;
int b;
};
#pragma pack()//取消按照n個字節對齊,是對#pragma pack(n)的一個反向操作
#pragma pack(2)//表示它后面的代碼都按照n個字節對齊
struct st4
{
char a;
int b;
};
#pragma pack()//取消按照n個字節對齊,是對#pragma pack(n)的一個反向操作
int main()
{
printf("%d\n",sizeof(struct st3) );
printf("%d\n",sizeof(struct st4) );
return 0;
}
3.2 定義結構體時指定__attribute__((packed))
3.2.1 用法
-
__attribute__ ((packed))
的作用就是告訴編譯器取消結構在編譯過程中的優化對齊,按照實際占用字節數進行對齊
,是GCC特有的語法。這個功能是跟操作系統沒關系,跟編譯器有關.
//用法如下
struct bbb
{
char a;
int b;
}__attribute__((packed));//直接按照實際占用字節來對齊,其實就是相當于按照1個字節對齊了
//這里計算sizeof(st3)=5
3.2.2 例子
#include <stdio.h>
struct st3
{
char a;
int b;
}__attribute__((packed));
struct __attribute__((packed)) st4
{
int b;
char a;
};
int main()
{
printf("%d\n",sizeof(struct st3) );
printf("%d\n",sizeof(struct st4) );
return 0;
}
原文鏈接:https://blog.csdn.net/qq_37233070/article/details/133791709
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-09-17 使用cache加快編譯速度的命令詳解_相關技巧
- 2022-09-22 uni ui 、color ui 圖標icon的使用
- 2022-04-09 Webservice 服務請求參數xml 嵌套問題/CDATA嵌套
- 2022-03-26 android獲取及監聽手機網絡狀態_Android
- 2023-11-16 【電腦Windows日常】解決Windows11 無法顯示office圖標的問題
- 2022-12-13 C++?Boost?StringAlgorithms超詳細講解_C 語言
- 2023-01-17 Qt中控件的函數使用教程分享_C 語言
- 2022-11-28 golang進程內存控制避免docker內oom_Golang
- 欄目分類
-
- 最近更新
-
- 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同步修改后的遠程分支