linux 改變GCC編譯器的位元組對齊方式
linux C 位元組對其簡介
在C語言中,結構是一種複合資料型別,其構成元素既可以是基本資料型別(如int、long、float等)的變數,也可以是一些複合資料型別(如陣列、結構、聯合等)的資料單元。
在結構中,編譯器為結構的每個成員按其自然對界(alignment)條件分配空間。各個成員按照它們被宣告的順序在記憶體中順序儲存,第一個成員的地址和整個結構的地址相同。
例如,下面的結構各成員空間分配情況:
struct test
{
char x1;
short x2;
float x3;
char x4;
};
結構的第一個成員x1,其偏移地址為0,佔據了第1個位元組。
第二個成員x2為short型別,其起始地址必須2位元組對界,因此,編譯器在x2和x1之間填充了一個空位元組。
第三個成員x3和第四個成員x4恰好落在其自然對界地址上,在它們前面不需要額外的填充位元組。
在test結構中,成員x3要求4位元組對界,是該結構所有成員中要求的最大對界單元,因而test結構的自然對界條件為4位元組,編譯器在成員x4後面填充了3個空位元組。整個結構所佔據空間為12位元組。
更改C編譯器的預設位元組對齊方式
在預設情況下,C編譯器為每一個變數或是資料單元按其自然對界條件分配空間。一般地,可以通過下面的方法來改變預設的對界條件:
方式一:
· 使用偽指令#pragma pack (n),C編譯器將按照n個位元組對齊。
· 使用偽指令#pragma pack (),取消自定義位元組對齊方式。
方式二:
· __attribute((aligned (n))),讓所作用的結構成員對齊在n位元組自然邊界上。如果結構中有成員的長度大於n,則按照最大成員的長度來對齊。
· __attribute__ ((packed)),取消結構在編譯過程中的優化對齊,按照實際佔用位元組數進行對齊。
以上的n = 1, 2, 4, 8, 16... 第一種方式較為常見。
在網路協議程式設計中,經常會處理不同協議的資料包文。一種方法是通過指標偏移的方法來得到各種資訊,但這樣做不僅程式設計複雜,而且一旦協議有變化,程式修改起來也比較麻煩。在瞭解了編譯器對結構空間的分配原則之後,我們完全可以利用這一特性定義自己的協議結構,通過訪問結構的成員來獲取各種資訊。這樣做,不僅簡化了程式設計,而且即使協議發生變化,我們也只需修改協議結構的定義即可,其它程式無需修改,省時省力。下面以TCP協議首部為例,說明如何定義協議結構。其協議結構定義如下:
#pragma pack(1) // 按照1位元組方式進行對齊
對齊原則:
1、基本型別變數起始地址要按一定規則對齊.
char 型別,其起始地址要1位元組邊界上,即其地址能被1整除(即任意地址即可)
short型別,其起始地址要2位元組邊界上,即其地址能被2整除
int 型別,其起始地址要4位元組邊界上,即其地址能被4整除
long型別,其起始地址要4位元組邊界上,即其地址能被4整除
float型別,其起始地址要4位元組邊界上,即其地址能被4整除
double型別,其起始地址要8位元組邊界上,即其地址能被8整除
注意:指標型別,其起始地址要在8位元組邊界上
2、結構例項起始址要在自己最大尺寸成員的對齊地址上
如最大尺寸的成員是short,則要基於2對齊
3、結構內成員的偏移量也要參照第1條,滿足相應倍數
如成員是short,則偏移量也是2的倍數.
這一條實際仍然是第1條規則的擴充套件,因為結構起始地址按最大倍數來,加上內部相應倍數,這樣成員絕對地址仍然滿足第1條規定
4、結構總尺寸也要對齊. 要為最大尺寸的成員的整數倍,
如果不是則要在結構最後補齊成整數倍
位元組對齊例項
#include <stdio.h>
// 使用系統預設的位元組對齊方式,32位機器一般為4位元組對齊;
struct person0{
char *name;
int age;
char score;
int id;
};
// 取消在編譯過程中的優化對齊,按照實際佔用位元組數進行對齊
struct person1{
char *name;
int age;
char score;
int id;
}__attribute__((packed));
// 構體成員對齊在4位元組邊界上
struct person2{
char *name;
int age;
char score;
int id;
} __attribute__((aligned (4)));
int main(int argc, char **argv)
{
printf("size of (struct person0) = %lu.\n", sizeof(struct person0));
printf("size of (struct person1) = %lu.\n", sizeof(struct person1));
printf("size of (struct person2) = %lu.\n", sizeof(struct person2));
return 0;
}
執行結果:
因64位系統,所以指標佔8位元組的資料記憶體,int 也是8位元組;
getconf命令可以獲取系統的基本配置資訊,比如作業系統位數,記憶體大小
檢視作業系統是多少位
相關文章
- 【編譯製導指令】#pragma pack - 位元組數基準對齊編譯
- golang 位元組對齊Golang
- Linux中gcc編譯工具LinuxGC編譯
- C++ 位元組對齊C++
- c/c++ 位元組對齊C++
- GCC編譯器背後的故事GC編譯
- 【C++】C++的位元組對齊C++
- 原創 【CentOS Linux 7】實驗4【gcc編譯器】CentOSLinuxGC編譯
- 【C/C++】5.位元組對齊和位元組填充C++
- iOS 記憶體位元組對齊iOS記憶體
- JWebAssembly:Java 位元組碼到 WebAssembly 編譯器WebJava編譯
- 探索gcc編譯最佳化細節 編譯器最佳化gcc -o3GC編譯
- [譯]JavaScript的新功能將改變正規表示式的編寫方式JavaScript
- python反編譯之位元組碼Python編譯
- Linux核心模組編譯Linux編譯
- 記錄一次gcc的編譯GC編譯
- GCC編譯過程(預處理->編譯->彙編->連結)GC編譯
- Jtti:美國Linux伺服器原始碼編譯的安裝方式JttiLinux伺服器原始碼編譯
- JVM 模板直譯器之如何根據位元組碼生成彙編碼?JVM
- 【譯】Visual Studio 的 Razor 編輯器的改進
- 記一次編譯GCC的經歷編譯GC
- GCC編譯和連結過程GC編譯
- Ubuntu 19.10將使用GCC 9作為預設編譯器UbuntuGC編譯
- Linux環境下, 原始碼編譯安裝詳解 (編譯CMake 3.15 和 gcc 5.3.0 為例)Linux原始碼編譯GC
- gcc 和 g++ 的聯絡和區別,使用 gcc 編譯 c++GC編譯C++
- linux對齊文字Linux
- 如何在64位Linux系統上用gcc編譯32位程式LinuxGC編譯
- vxe-table 設定單元格對齊方式,左對齊、右對齊
- CAD表格文字對齊方式
- transform改變定位元素的包含塊ORM
- ES6模組化改變前端的原生開發方式前端
- gcc編譯階段列印巨集定義的內容GC編譯
- Vue3原始碼分析——編譯模組和編譯器Vue原始碼編譯
- 32位支援:使用 GCC 交叉編譯GC編譯
- Android ImageView對齊方式設定AndroidView
- m基於BP譯碼演算法的LDPC編譯碼matlab誤位元速率模擬,對比不同的位元速率演算法編譯Matlab
- 高效學習Linux核心——核心模組編譯Linux編譯
- PHP MySQL (二)物件導向 增刪查改 (預編譯方式)PHPMySql物件編譯