在大多數狀況下,編譯器和C庫透明地幫你處理對齊問題。POSIX 標明瞭經過malloc( ), calloc( ), 和 realloc( ) 返回的地址對於任何的C類型來講都是對齊的。在Linux中,這些函數返回的地址在32位系統是以8字節爲邊界對齊,在64位系統是以16字節爲邊界對齊的。有時候,對於更大的邊界,例如頁面,程序員須要動態的對齊。雖然動機是多種多樣的,但最多見的是直接塊I/O的緩存的對齊或者其它的軟件對硬件的交互,所以,POSIX 1003.1d提供一個叫作posix_memalign( )的函數:程序員
/* one or the other -- either suffices */ #define _XOPEN_SOURCE 600 #define _GNU_SOURCE #include <stdlib.h> int posix_memalign (void **memptr, size_t alignment, size_t size);
* See http://perens.com/FreeSoftware/ElectricFence/ and http://valgrind.org, respectively.
調用posix_memalign( )成功時會返回size字節的動態內存,而且這塊內存的地址是alignment的倍數。參數alignment必須是2的冪,仍是void指針的大小的倍數。返回的內存塊的地址放在了memptr裏面,函數返回值是0.數組
調用失敗時,沒有內存會被分配,memptr的值沒有被定義,返回以下錯誤碼之一:緩存
EINVAL函數
參數不是2的冪,或者不是void指針的倍數。spa
ENOMEM指針
沒有足夠的內存去知足函數的請求。內存
要注意的是,對於這個函數,errno不會被設置,只能經過返回值獲得。編譯器
由posix_memalign( )得到的內存經過free( )釋放。用法很簡單:it
char *buf; int ret; /* allocate 1 KB along a 256-byte boundary */ ret = posix_memalign (&buf, 256, 1024); if (ret) { fprintf (stderr, "posix_memalign: %s\n", strerror (ret)); return -1; } /* use 'buf'... */ free (buf);
與對齊有關的問題的範圍要超過標準類型的天然對齊和動態存儲器地分配。例如,非標準和複雜的類型比標準類型有更復雜的要求。另外,對對齊的關注在給指向不一樣類型的指針賦值和使用強轉時顯得加倍的重要。編譯
非標準類型。非標準和複雜的數據類型的對齊比簡單的天然對齊有着更多的要求。這裏四個有頗有用的方法:
•一個結構的對齊要求是和它的成員中最大的那個類型同樣的。例如,一個結構中最大的是以4字節對齊的32bit的整形,那麼這個結構至少以4字節對齊。
•結構也引入了填充的須要,用來保證每個成員都符合本身的對齊要求。因此,若是一個char (可能以1字節對齊)後跟着一個int (可能以4字節對齊),編譯器會自動地插入3個字節做爲填充來保證int以4字節對齊。
程序員有時候排列結構裏面的成員-例如,以大小來遞減-來是使用做填充的垃圾空間最少。GCC的選項- Wpadded能對這些努力有幫助,由於它使得在編譯器偷偷插入填充時產生警告。
•一個聯合的對齊和聯合裏最大的類型同樣。
•一個數組的對齊和數組裏的元素同樣。因此,數組的對齊並不比單單的一個成員嚴格,這樣能使數組裏面的全部成員都是天然對齊的。