__attribute__ 機制詳解


https://blog.csdn.net/weaiken/article/details/88085360

 

__attribute 語法的來源
GNU C 的一大特色就是__attribute__ 機制。attribute 可以設置函數屬性(Function Attribute)、變量屬性(Variable Attribute)和類型屬性(Type Attribute)。

其位置約束為: 放於聲明的尾部“;” 之前

attribute 書寫特征為: attribute 前后都有兩個下划線,並切后面會緊跟一對原括弧,括弧里面是相應的__attribute__ 參數。

attribute 語法格式為: attribute ((attribute-list))

當__attribute__ 用於修飾對象時,它就如同C 語言語法體系結構的類型限定符,跟const , volatile , restrict 等屬一類。
當__attribute__ 用於修飾函數時,它就相當於一個函數說明符,跟inline,Noreturn 屬同一類。
當__attribute_ 用於修飾一個結構體,聯合體或者枚舉類型,該限定符只能放在類型標識符之前。

__attribute 所支持的類型
當我們需要識別當前編譯器能否支持GNU 語法拓展,我們可以使用 __GNU __ 宏作為區分

函數屬性(Function Attribute)類型屬性(Type Attributes)變量屬性(Variable Attribute)Clang特有的

noreturn                              aligned                                alias                                        availability

noinline                              packed                                 at(address)                        overloadable

always_inline                       bitband                                aligned

flatten                                                                        deprecated

pure                                                                                noinline

const                                                                        packed

constructor                                                                weak

destructor                                                                weakref(“target”)

sentinel                                                                        section(“name”)

format                                                                        unused

format_arg                                                                used

section                                                                        visibility(“visibility_type”)

used                                                                       zero_init

unused

deprecated

weak

malloc

alias

warn_unused_result

nonnull

nothrow (不拋出C++ 異常)

 

常用函數屬性

attribute((Noreturn)) function attribute

表示沒有返回值

 

這個屬性告訴編譯器函數不會返回,這可以用來抑制關於未達到代碼路徑的錯誤。 C庫函數abort()和exit()都使用此屬性聲明:

extern void exit(int)   __attribute__((noreturn));

extern void abort(void) __attribute__((noreturn));

 

attribute((always_inline)) function attribute

對於聲明為內聯的函數,會強制優化。所有加了attribute((always_inline))的函數再被調用時不會被編譯成函數調用而是直接擴展到調用函數體內。

 

attribute((noinline)) function attribute

與上面的相反,聲明為非內聯函數。

 

attribute((flatten)) function attribute

用此修飾的函數,在函數中調用的每一個函數都將盡可能地做內聯處理。而用flatten 屬性修飾的函數,是否內聯處理,就要根據編譯器當前的編譯選項以及當前上下文來定。

 

attribute((pure)) function attribute

用pure屬性修飾的函數用來說明該函數除了返回值之外沒有其他任何 效果,並且該函數所返回的值僅僅依賴於函數的形參以及/或全局對象。用 pure屬性所修飾的函數可以用來輔助編譯器做消除公共子表達式以及幫助 做循環優化,使用這種函數就好比使用算術操作符一般。

用pure屬性所修飾的函數體內不應該含有無限循環,不應該對volatile 修飾的全局對象進行訪問或是對多個線程所共享的全局對象進行訪問,也 不應該訪問其他系統資源,比如對文件、套接字等進行操作。簡而言之, 對同一個使用pure屬性修飾的函數連續做兩次調用(如果該函數帶有參 數,那么兩次調用應該用同樣的實參),那么這兩次調用所返回的結果應 該始終是相同的。因此,用pure屬性所修飾的函數也很容易讓編譯器做內 聯處理。

attribute((const)) function attribute

用const屬性修飾的函數與用pure屬性修飾的十分類似,不過const屬性比pure更嚴格,它要求函數不能讀全局對象。此外,用const屬性修飾的函數的參數不能是一個指針類型,而且在用const屬性修飾的函數內往往不能調用一個非const屬性的函數。

 

attribute((sentinel)) function attribute

提醒程序員“此可變參數函數需要一個NULL作為最后一個參數。

 

attribute((format)) function attribute

attribute format屬性可以給被聲明的函數加上類似printf或者scanf的特征,它可以使編譯器檢查函數聲明和函數實際調用參數之間的格式化字符串是否匹配。format屬性告訴編譯器,按照printf, scanf等標准C函數參數格式規則對該函數的參數進行檢查。這在我們自己封裝調試信息的接口時非常的有用。

 

format的語法格式為:

format (archetype, string-index, first-to-check)

其中,“archetype”指定是哪種風格;“string-index”指定傳入函數的第幾個參數是格式化字符串;“first-to-check”指定從函數的第幾個參數開始按上述規則進行檢查。

具體的使用如下所示:

attribute((format(printf, a, b)))

attribute((format(scanf, a, b)))

其中參數m與n的含義為:

    a:第幾個參數為格式化字符串(format string);

    b:參數集合中的第一個,即參數“…”里的第一個參數在函數參數總數排在第幾。

 

attribute((section(“name”))) function attribute

attribute((section(“name”))) 其作用是將作用的函數或數據放入指定名為"section_name"對應的段中

 

static void __attribute((section("__TEXT,MySection" ))) myFun1(void)

{

  print("");

}

attribute((unused)) function attribute

attribute((unused)) 其作用是即使沒有使用這個函數,編譯器也不警告。

 

attribute((used)) function attribute

attribute((used)) 其作用是告訴編譯器避免被鏈接器因為未用過而被優化掉。

 

attribute((visibility(“visibility_type”))) function attribute

visibility_type 類型有4種:

 

default

default 可見性是默認的符號鏈接可見性,如果我們不指定visibility 屬性,那么默認就使用默認的可見性。默認可見性的對象與函數可以直接在其他模塊中引用,包括在動態鏈接庫中 ,它屬於一個正常,完整的外部連接。

hidden

該符號不存放在動態符號表中,因此,其他可執行文件或共享庫都無法直接引用它。使用函數指針可進行間接引用。

internal

除非由 特定於處理器的應用二進制接口 (psABI) 指定,否則,內部可見性意味着不允許從另一模塊調用該函數。

protected

該符號存放在動態符號表中,但定義模塊內的引用將與局部符號綁定。也就是說,另一模塊無法覆蓋該符號。

attribute((weak)) function attribute

什么是弱符號?

若兩個或兩個以上全局符號(函數或變量名)名字一樣,而其中之一聲明為weak symbol(弱符號),則這些全局符號不會引發重定義錯誤。鏈接器會忽略弱符號,去使用普通的全局符號來解析所有對這些符號的引用,但當普通的全局符號不可用時,鏈接器會使用弱符號。當有函數或變量名可能被用戶覆蓋時,該函數或變量名可以聲明為一個弱符號。弱符號也稱為weak alias(弱別名)。

attribute((weakref(“target”))) function attribute

attribute((weakref))為弱引用,請注意引用與定義的區別。weakref就是申明某個引用為弱引用,弱引用時如果需引用符號不存在也不會鏈接出錯,而是將需要引用的符號定義為WEAK屬性及0地址(跟前面的WEAK屬性很相似吧)。

weakref的用法有點特別,必須要配合alias使用及必須是static定義。attribute((weak(“target”)))相當於__attribute__((weakref,alias(“target”)))

 

attribute((malloc)) function attribute

attribute((malloc)) 是由如此標記的函數返回的塊不得包含任何指向其他對象的指針.目的是幫助編譯器估計哪些指針可能指向同一個對象:該屬性告訴GCC它不必擔心你的函數返回的對象可能包含指向它正在跟蹤的其他東西的指針.

 

attribute((aligned)) type attribute

aligned 屬性修飾一個函數時,用於直至該函數的首地址至少需要 aligned 個字節對齊。

 

什么是字節對齊(可以跳過)

現代計算機中內存空間都是按照字節(byte)划分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經常在特定的內存地址訪問,這就需要各類型數據按照一定的規則在空間上排列,而不是順序地一個接一個地排放,這就是對齊.

 

字節對齊的好處(可以跳過)

為了提高效率,計算機從內存中取數據是按照一個固定長度的。以32位機為例,它每次取32個位,也就是4個字節(每字節8個位)。字節對齊有什么好處?以int型數據為例,如果它在內存中存放的位置按4字節對齊,也就是說1個int的數據全部落在計算機一次取數的區間內,那么只需要取一次就可以了.

 

對齊原則:

char 偏移量必須為sizeof(char) 即1的倍數,可以任意地址開始存儲

short 偏移量必須為sizeof(short) 即2的倍數,只能從0,2,4…等2的倍數的地址開始存儲

int 偏移量必須為sizeof(int) 即4的倍數,只能從0,4,8…等4的倍數的地址開始存儲

float 偏移量必須為sizeof(float) 即4的倍數,只能從0,4,8…等4的倍數的地址開始存儲

double 偏移量必須為sizeof(double)即8的倍數,只能從0,8,16…等地址開始存儲

 

結構體如何設定字節對齊

當未明確指定時,以結構體中最長的成員的長度為其有效值,上面的兩個結構體都是int類型最長,也就是4字節對齊

結構體作為成員:如果一個結構里有某些結構體成員,則結構體成員要從其內部最大元素大小的整數倍地址開始存儲.(struct a里存有struct b,b里有char,int ,double等元素,那b應該從8的整數倍開始存儲.)

結構體的總大小,也就是sizeof的結果,必須是其內部最大成員的整數倍.不足的要補齊.

函數的對齊方式寫法

 

noreturnalignedaliasavailabilitynoinlinepackedat(address)overloadablealways_inlinebitbandalignedflattendeprecatedpurenoinlineconstpackedconstructorweakdestructorweakref(“target”)sentinelsection(“name”)formatunusedformat_argusedsectionvisibility(“visibility_type”)usedzero_initunuseddeprecatedweakmallocaliaswarn_unused_resultnonnullnothrow (不拋出C++ 異常)常用函數屬性attribute((Noreturn)) function attribute表示沒有返回值
這個屬性告訴編譯器函數不會返回,這可以用來抑制關於未達到代碼路徑的錯誤。 C庫函數abort()和exit()都使用此屬性聲明:extern void exit(int)   __attribute__((noreturn));extern void abort(void) __attribute__((noreturn));12attribute((always_inline)) function attribute對於聲明為內聯的函數,會強制優化。所有加了attribute((always_inline))的函數再被調用時不會被編譯成函數調用而是直接擴展到調用函數體內。
attribute((noinline)) function attribute與上面的相反,聲明為非內聯函數。
attribute((flatten)) function attribute用此修飾的函數,在函數中調用的每一個函數都將盡可能地做內聯處理。而用flatten 屬性修飾的函數,是否內聯處理,就要根據編譯器當前的編譯選項以及當前上下文來定。
attribute((pure)) function attribute用pure屬性修飾的函數用來說明該函數除了返回值之外沒有其他任何 效果,並且該函數所返回的值僅僅依賴於函數的形參以及/或全局對象。用 pure屬性所修飾的函數可以用來輔助編譯器做消除公共子表達式以及幫助 做循環優化,使用這種函數就好比使用算術操作符一般。用pure屬性所修飾的函數體內不應該含有無限循環,不應該對volatile 修飾的全局對象進行訪問或是對多個線程所共享的全局對象進行訪問,也 不應該訪問其他系統資源,比如對文件、套接字等進行操作。簡而言之, 對同一個使用pure屬性修飾的函數連續做兩次調用(如果該函數帶有參 數,那么兩次調用應該用同樣的實參),那么這兩次調用所返回的結果應 該始終是相同的。因此,用pure屬性所修飾的函數也很容易讓編譯器做內 聯處理。
以下是使用:————————————————版權聲明:本文為CSDN博主「weaiken」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/weaiken/article/details/88085360


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM