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
- 位元組對齊小談
- C++ 位元組對齊C++
- <摘錄>位元組對齊(強制對齊以及自然對齊)
- Linux gcc編譯器安裝LinuxGC編譯
- c/c++ 位元組對齊C++
- 記憶體位元組對齊記憶體
- gcc 編譯器與 clang 編譯器GC編譯
- GCC編譯器的使用GC編譯
- 【C++】C++的位元組對齊C++
- 【C/C++】5.位元組對齊和位元組填充C++
- iOS 記憶體位元組對齊iOS記憶體
- linux下的gcc編譯LinuxGC編譯
- JWebAssembly:Java 位元組碼到 WebAssembly 編譯器WebJava編譯
- GCC編譯器背後的故事GC編譯
- FreeBSD中的GNU C編譯器--編譯器GCC(轉)編譯GC
- Linux中gcc編譯工具LinuxGC編譯
- 安裝 GCC 編譯器(轉)GC編譯
- gcc編譯GC編譯
- Linux上安裝GCC編譯器過程(轉)LinuxGC編譯
- 編譯器GCC與Clang的異同編譯GC
- <摘錄>位元組對齊與結構體大小結構體
- 開源編譯器 GCC 跨越 5.0,釋出 GCC 5.1編譯GC
- 原創 【CentOS Linux 7】實驗4【gcc編譯器】CentOSLinuxGC編譯
- linux下gcc/g++編譯用法LinuxGC編譯
- 探索gcc編譯最佳化細節 編譯器最佳化gcc -o3GC編譯
- C/C++ 結構體位元組對齊詳解C++結構體
- 淺談虛擬函式表與位元組對齊函式
- C語言:記憶體位元組對齊詳解C語言記憶體
- C/C++—— 記憶體位元組對齊規則C++記憶體
- [譯]JavaScript的新功能將改變正規表示式的編寫方式JavaScript
- python反編譯之位元組碼Python編譯
- gcc編譯器小知識FAQ(轉)GC編譯
- Myeclipse如何改變編碼方式Eclipse
- opensuse linux安裝gcc編譯環境LinuxGC編譯
- 點陣圖四位元組對齊問題