attribute的用法總結

2021-05-23 22:05:14 字數 4576 閱讀 5029

__attribute__可以設定函式屬性(function attribute)、變數屬性(variable attribute)和型別屬性(type attribute)。

__attribute__書寫特徵是:__attribute__前後都有兩個下劃線,並切後面會緊跟一對原括弧,括弧裡面是相應的__attribute__引數。

__attribute__語法格式為:

__attribute__ ((attribute-list))

其位置約束為:

放於宣告的尾部「;」之前。

函式屬性可以幫助開發者把一些特性新增到函式宣告中,從而可以使編譯器在錯誤檢查方面的功能更強大。__attribute__機制也很容易同非gnu應用程式做到相容之功效。

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__((format(printf,m,n)))

是常用的,而另一種卻很少見到。下面舉例說明,其中myprint為自己定義的乙個帶有可變引數的函式,其功能類似於printf:

//m=1

;n=2

extern void myprint(const char *format,...) __attribute__((format(printf,1,2)));

//m=2

;n=3

extern void myprint(int l,const char *format,...) __attribute__((format(printf,2,3)));

需要特別注意的是,如果myprint是乙個函式的成員函式,那麼m和n的值可有點「懸乎」了,例如:

//m=3

;n=4

extern void myprint(int l,const char *format,...) __attribute__((format(printf,3,4)));

其原因是,類成員函式的第乙個引數實際上乙個「隱身」的「this」指標。(有點c++基礎的都知道點this指標,不知道你在這裡還知道嗎?)

__attribute__ const

該屬性只能用於帶有數值型別引數的函式上。當重複呼叫帶有數值引數的函式時,由於返回值是相同的,所以此時編譯器可以進行優化處理,除第一次需要運算外,其它只需要返回第一次的結果就可以了,進而可以提高效率。該屬性主要適用於沒有靜態狀態(static state)和***的一些函式,並且返回值僅僅依賴輸入的引數。

為了說明問題,下面舉個非常「糟糕」的例子,該例子將重複呼叫乙個帶有相同引數值的函式,具體如下:

extern int square(int n) __attribute__((const));
...
for (i = 0; i < 100; i++ )
通過新增__attribute__((const))宣告,編譯器只呼叫了函式一次,以後只是直接得到了相同的乙個返回值。

事實上,const引數不能用在帶有指標型別引數的函式中,因為該屬性不但影響函式的引數值,同樣也影響到了引數指向的資料,它可能會對**本身產生嚴重甚至是不可恢復的嚴重後果。

並且,帶有該屬性的函式不能有任何***或者是靜態的狀態,所以,類似getchar()或time()的函式是不適合使用該屬性的。

同時使用多個屬性

可以在同乙個函式宣告裡使用多個__attribute__,並且實際應用中這種情況是十分常見的。使用方式上,你可以選擇兩個單獨的__attribute__,或者把它們寫在一起,可以參考下面的例子:

/* 把類似printf的訊息傳遞給stderr 並退出 */
extern void die(const char *format, ...)
__attribute__((noreturn))
__attribute__((format(printf, 1, 2)));
或者寫成
extern void die(const char *format, ...)
__attribute__((noreturn, format(printf, 1, 2)));
如果帶有該屬性的自定義函式追加到庫的標頭檔案裡,那麼所以呼叫該函式的程式都要做相應的檢查。

需要說明的是,__attribute__適用於函式的宣告而不是函式的定義。所以,當需要使用該屬性的函式時,必須在同乙個檔案裡進行宣告

在使用__attribute__引數時,你也可以在引數的前後都加上「__」(兩個下劃線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的標頭檔案裡使用它而不用關心標頭檔案裡是否有重名的巨集定義。

aligned (alignment)

該屬性規定變數或結構體成員的最小的對齊格式,以位元組為單位。例如:

int x __attribute__ ((aligned (16))) = 0;
編譯器將以16位元組(注意是位元組byte不是位bit)對齊的方式分配乙個變數
packed

使用該屬性可以使得變數或者結構體成員使用最小的對齊方式,即對變數是一位元組對齊,對域(field)是位對齊。

下面的例子中,x成員變數使用了該屬性,則其值將緊放置在a的後面:

struct test

;
關鍵字__attribute__也可以對結構體(struct)或共用體(union)進行屬性設定。大致有六個引數值可以被設定,即:aligned, packed, transparent_union, unused, deprecated 和 may_alias。

在使用__attribute__引數時,你也可以在引數的前後都加上「__」(兩個下劃線),例如,使用__aligned__而不是aligned,這樣,你就可以在相應的標頭檔案裡使用它而不用關心標頭檔案裡是否有重名的巨集定義。

aligned (alignment)

該屬性設定乙個指定大小的對齊格式(以位元組為單位),例如:

struct s __attribute__ ((aligned (8)));

typedef int more_aligned_int __attribute__ ((aligned (8)));

該宣告將強制編譯器確保(盡它所能)變數型別為struct s或者more-aligned-int的變數在分配空間時採用8位元組對齊方式。

如上所述,你可以手動指定對齊的格式,同樣,你也可以使用預設的對齊方式。如果aligned後面不緊跟乙個指定的數字值,那麼編譯器將依據你的目標機器情況使用最大最有益的對齊方式。例如:

struct s __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)。

下面的例子中,my-packed-struct型別的變數陣列中的值將會緊緊的靠在一起,但內部的成員變數s不會被「pack」,如果希望內部的成員變數也被packed的話,my-unpacked-struct也需要使用packed進行相應的約束。

struct my_unpacked_struct

char c;

int i;

struct my_packed_struct

char c;

int i;

struct my_unpacked_struct s;

}__attribute__ ((__packed__));

c 特性 Attribute 學習總結1

特性是用於在執行時傳遞程式中各種元素 類 方法 結構 列舉 元件等 的行為資訊的宣告性標籤。官方的解讀不好理解,舉個常用的例子,平時會在類的上面加上 serializable serializable就是testclass這個類的乙個特性,它表示這個類是可以被序列化的。如下圖 net框架提供兩種型別...

c 特性 Attribute 學習總結2

通過特性提供額外行為的例項 自定義特性做資料驗證 效驗屬性值的大小和非空 學生類中有個qq的屬性,效驗qq不能小於100000 5位數 不能大於999999999999 12位數 並且qq的屬性不能為空。如果滿足這些效驗返回true,否則返回false。宣告乙個抽象類,所有的自定義特性都繼承自這個抽...

特性(Attribute)的用處

attribute特性,可以往程式集中寫入一些元資料。微軟類庫中自帶很多 attribute類,某些時候,需要對類標註一下 attribute。那麼自定義 attribute的用處是什麼的,或者說,什麼時候我們需要自定義 attribute。在我看來,自定義attribute沒啥用。常規的專案開發中...