網(wǎng)站首頁 編程語言 正文
1. 默認字節(jié)對齊
- 在所有結(jié)構(gòu)體成員的字節(jié)長度都沒有超出操作系統(tǒng)基本字節(jié)單位(32位操作系統(tǒng)是4,64位操作系統(tǒng)是8)的情況下
按照結(jié)構(gòu)體中字節(jié)最大的變量長度來對齊; - 若結(jié)構(gòu)體中某個變量字節(jié)超出操作系統(tǒng)基本字節(jié)單位
那么就按照系統(tǒng)字節(jié)單位來對齊。
注意:
并不是32位就直接按照4個字節(jié)對齊,64位就按照8個字節(jié)對齊。
2. 為什么存在字節(jié)對齊
2.1 了解 CPU 一次讀取內(nèi)存數(shù)
CPU 一次能讀取多少內(nèi)存要看數(shù)據(jù)總線是多少位
- 如果是16位,則一次只能讀取 2 個字節(jié)
- 如果是32位,則可以讀取 4 個字節(jié),并且
CPU 不能跨內(nèi)存區(qū)間訪問
。
例子:
假設(shè)有這樣一個結(jié)構(gòu)體如下:
struct st3
{
char a;
int b;
};
//在32位系統(tǒng)下,它就應(yīng)該是8個字節(jié)的。
假設(shè)地址空間是類似下面這樣的:
-
在沒有字節(jié)對齊的情況下,
- 變量 a 就是占用了 0x00000001 這一個字節(jié),而變量b則是占用了 0x00000002~0x000000005 這四個字節(jié)
- 此時 cpu 如果想從內(nèi)存中讀取變量 b,首先要從變量 b 的開始地址 0x00000002讀到 0x0000004,然后再讀取一次 0x00000005 這個字節(jié),相當于讀一個 int,cpu 從內(nèi)存讀取了兩次。
-
如果進行字節(jié)對齊的話
- 變量 a 還是占用了 0x00000001 這一個字節(jié),而變量 b 則是占用了 0x00000005~0x00000008 這四個字節(jié)
- 此時 cpu 要讀取變量 b 的話,就直接一次性從 0x00000005 讀到 0x00000008 ,就一次全部讀取出來了。
總結(jié):
-
字節(jié)對齊的根本原因其實在于 cpu 讀取內(nèi)存的效率問題
,對齊以后,cpu讀取內(nèi)存的效率會更快。 - 對齊的時候 0x00000002~0x00000004 這三個字節(jié)是浪費的,所以字節(jié)對齊實際上也有那么點以空間換時間的意思,具體寫代碼的時候怎么選擇,其實是看個人的。
3. 編碼時手動設(shè)置對齊
兩種。
3.1 代碼里添加預(yù)編譯標識 pragma pack(n)
3.1.1 用法
- 使用預(yù)編譯指令 #pragma pack (n) 來告訴編譯器,使用我們指定的對齊值來取代缺省的。
- 對齊的算法: 隨編譯器變化
//用法如下
#pragma pack(n)//表示它后面的代碼都按照n個字節(jié)對齊
struct st3
{
char a;
int b;
};
#pragma pack()//取消按照n個字節(jié)對齊,是對#pragma pack(n)的一個反向操作
3.1.2 例子
#include <stdio.h>
#pragma pack(1)//表示它后面的代碼都按照n個字節(jié)對齊
struct st3
{
char a;
int b;
};
#pragma pack()//取消按照n個字節(jié)對齊,是對#pragma pack(n)的一個反向操作
#pragma pack(2)//表示它后面的代碼都按照n個字節(jié)對齊
struct st4
{
char a;
int b;
};
#pragma pack()//取消按照n個字節(jié)對齊,是對#pragma pack(n)的一個反向操作
int main()
{
printf("%d\n",sizeof(struct st3) );
printf("%d\n",sizeof(struct st4) );
return 0;
}
3.2 定義結(jié)構(gòu)體時指定__attribute__((packed))
3.2.1 用法
-
__attribute__ ((packed))
的作用就是告訴編譯器取消結(jié)構(gòu)在編譯過程中的優(yōu)化對齊,按照實際占用字節(jié)數(shù)進行對齊
,是GCC特有的語法。這個功能是跟操作系統(tǒng)沒關(guān)系,跟編譯器有關(guān).
//用法如下
struct bbb
{
char a;
int b;
}__attribute__((packed));//直接按照實際占用字節(jié)來對齊,其實就是相當于按照1個字節(jié)對齊了
//這里計算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
- 上一篇:沒有了
- 下一篇:沒有了
相關(guān)推薦
- 2022-05-23 iOS實現(xiàn)垂直滑動條效果_IOS
- 2022-06-29 python循環(huán)神經(jīng)網(wǎng)絡(luò)RNN函數(shù)tf.nn.dynamic_rnn使用_python
- 2022-07-15 關(guān)于在Redis中使用Pipelining加速查詢的問題_Redis
- 2022-02-17 ERROR: but there is no HDFS_NAMENODE_USER defined.
- 2022-08-04 Unity中協(xié)程IEnumerator的使用方法介紹詳解_C#教程
- 2021-12-11 Docker容器編譯LNMP的實現(xiàn)示例_docker
- 2022-04-12 React工作流程及Error?Boundaries實現(xiàn)過程講解_React
- 2022-04-04 運行npm run dev報錯(已解決)
- 欄目分類
-
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支