__attribute__是GNU C提供的一種機制。__attribute__可以設定函數屬性(Function Attribute)、變數屬性(Variable Attribute)和類型屬性(Type Attribute)。
__attribute__書寫特徵是:__attribute__前後都有兩個底線,並切後面會緊跟一對原括弧,括弧裡面是相應的__attribute__參數。
__attribute__文法格式為:
__attribute__ ((attribute-list))
其位置約束為:
放於聲明的尾部“;”之前。
函數屬性(Function Attribute)
函數屬性可以協助開發人員把一些特性添加到函式宣告中,從而可以使編譯器在錯誤檢查方面的功能更強大。__attribute__機制也很容易同非GNU應用程式做到相容之功效。
GNU CC需要使用 –Wall編譯器來擊活該功能,這是控制警告資訊的一個很好的方式。下面介紹幾個常見的屬性參數。
__attribute__ format
該__attribute__屬性可以給被聲明的函數加上類似printf或者scanf的特徵,它可以使編譯器檢查函式宣告和函數實際調用參數之間的格式化字串是否匹配。該功能十分有用,尤其是處理一些很難發現的bug。
format的文法格式為:
format (archetype, string-index, first-to-check)
format屬性告訴編譯器,按照printf, scanf, strftime或strfmon的參數表格式規則對該函數的參數進行檢查。“archetype”指定是哪種風格;“string-index”指定傳入函數的第幾個參數是格式化字串;“first-to-check”指定從函數的第幾個參數開始按上述規則進行檢查。
具體使用格式如下:
__attribute__((format(printf,m,n)))
__attribute__((format(scanf,m,n)))
其中參數m與n的含義為:
m:第幾個參數為格式化字串(format string);
n:參數集合中的第一個,即參數“…”裡的第一個參數在函數參數總數排在第幾。
__attribute__ noreturn
該屬性通知編譯器函數從不傳回值,當遇到類似函數需要傳回值而卻不可能運行到傳回值處就已經退出來的情況,該屬性可以避免出現錯誤資訊。C庫函數中的abort()和exit()的聲明格式就採用了這種格式,如下所示:
extern void exit(int) __attribute__((noreturn));extern void abort(void) __attribute__((noreturn));
__attribute__ const
該屬性只能用於帶有數實值型別參數的函數上。當重複調用帶有數值參數的函數時,由於傳回值是相同的,所以此時編譯器可以進行最佳化處理,除第一次需要運算外, 其它只需要返回第一次的結果就可以了,進而可以提高效率。該屬性主要適用於沒有靜態狀態(static state)和副作用的一些函數,並且傳回值僅僅依賴輸入的參數。
關鍵字__attribute__也可以對變數(variable)或結構體成員(structure field)進行屬性設定。這裡給出幾個常用的參數的解釋,更多的參數可參考本文給出的串連。
在使用__attribute__參數時,你也可以在參數的前後都加上“__”(兩個底線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的標頭檔裡使用它而不用關心標頭檔裡是否有重名的宏定義。
aligned (alignment)
該屬性規定變數或結構體成員的最小的對齊格式,以位元組為單位。例如:
int x __attribute__ ((aligned (16))) = 0; 編譯器將以16位元組(注意是位元組byte不是位bit)對齊的方式分配一個變數。也可以對結構體成員變數設定該屬性,例如,建立一個雙字對齊的int對,可以這麼寫:
struct foo { int x[2] __attribute__ ((aligned (8))); }; 如上所述,你可以手動指定對齊的格式,同樣,你也可以使用預設的對齊。如果aligned後面不緊跟一個指定的數字值,那麼編譯器將依據你的目標機器 情況使用最大最有益的對齊。例如:
short array[3] __attribute__ ((aligned)); 選擇針對目標機器最大的對齊,可以提高拷貝操作的效率。
aligned屬性使被設定的對象佔用更多的空間,相反的,使用packed可以減小對象佔用的空間。
需要注意的是,attribute屬性的效力與你的連接器也有關,如果你的連接器最大隻支援16位元組對齊,那麼你此時定義32位元組對齊也是無濟於事的。
packed
使用該屬性可以使得變數或者結構體成員使用最小的對齊,即對變數是一位元組對齊,對域(field)是位對齊。
關鍵字__attribute__也可以對結構體(struct)或共用體(union)進行屬性設定。大致有六個參數值可以被設定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias。
在使用__attribute__參數時,你也可以在參數的前後都加上“__”(兩個底線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的標頭檔裡使用它而不用關心標頭檔裡是否有重名的宏定義。
aligned (alignment)
該屬性設定一個指定大小的對齊格式(以位元組為單位),例如:
struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef int more_aligned_int __attribute__ ((aligned (8)));
該聲明將強制編譯器確保(盡它所能)變數類型為struct S或者more-aligned-int的變數在分配空間時採用8位元組對齊。
如上所述,你可以手動指定對齊的格式,同樣,你也可以使用預設的對齊。如果aligned後面不緊跟一個指定的數字值,那麼編譯器將依據你的目標機器情況使用最大最有益的對齊。例如:
struct S { short f[3]; } __attribute__ ((aligned));
這裡,如果sizeof(short)的大小為2(byte),那麼,S的大小就為6。取一個2的次方值,使得該值大於等於6,則該值為8,所以編譯器將設定S類型的對齊為8位元組。
aligned屬性使被設定的對象佔用更多的空間,相反的,使用packed可以減小對象佔用的空間。
需要注意的是,attribute屬性的效力與你的連接器也有關,如果你的連接器最大隻支援16位元組對齊,那麼你此時定義32位元組對齊也是無濟於事的。
packed
使用該屬性對struct或者union類型進行定義,設定其類型的每一個變數的記憶體約束。當用在enum類型定義時,暗示了應該使用最小完整的類型 (it indicates that the smallest integral type should be used)。