核心中的gcc擴充

來源:互聯網
上載者:User

本文收集Linux核心中用到的gcc的C擴充。轉載請註明出處http://blog.csdn.net/enjoysilence/article/details/8929729。

1. 運算式中的語句和聲明(Statements and Declarations in Expressions)

用一對大括弧{}把多條語句括起來,就構成了一條複合陳述式,再用一對圓排號()將這條複合陳述式括起就構成了一條複合陳述式運算式,這個運算式的值就是複合陳述式中最後一條子運算式的值,這與Shell指令碼有些類似,例如下面這條語句將foo()的絕對值賦值給整型變數a:

int a = ({ int y = foo ();            int z;            if (y > 0) z = y;            else z = - y;            z; })

這個特性可以使宏定義更加安全,在標準C中,通常這樣來定義一個求最大值的宏:

#define max(x,y) ((x) > (y) ? (x):(y))

這裡的x和y被求值了兩次,對有副作用(如i++)的運算元會產生錯誤的結果。但如果使用Gcc的複合運算式,就可以使宏定義變得安全:

#define max(x, y) ({                            \        typeof(x) _max1 = (x);                  \        typeof(y) _max2 = (y);                  \        (void) (&_max1 == &_max2);              \        _max1 > _max2 ? _max1 : _max2; })

這是一個泛型宏,其中的typeof就像typedef的逆運算一樣,取出運算元的類型,詳見下面關於typeof的說明。

(void) (&_max1 == &_max2); 

語句用來確認x和y的類型是否相同 ,若不相同Gcc會給出錯誤提示,詳見另一篇Blog《關於(void)(&_min1 == &min2)》。
2. typeof

typeof的含義如同typedef的逆運算,即取出其運算元的類型。它的文法卻如同sizeof,其運算元可以是運算式也可以是類型,如下例所示:

typeof (a[0](1)) /*運算元是運算式*/typeof (char *)  /*運算元是類型*/

typeof關鍵字常用來構造泛型宏,例如上方的max宏定義。
下面是更多的例子:

typeof (*x) y;    /*聲明一個類型為*x的變數y*/typeof (*x) z[4]; /*聲明一個長為4的數組z,數組元素為*x類型*/     typeof (typeof (char *)[4]) a; /*等價於char *a[4]*/
3. 分支預測提示

學過彙編的同學都知道,條件陳述式由jmp族指令來實現。為了防止程式執行時過多的跳轉影響效能,通常將最可能的情況安排在緊鄰jmp指令之後。Gcc有個內建函數__builtin_expect用來指示編譯器可能的分支,它的聲明如下

long __builtin_expect (long exp, long c)

這個函數的語義是期望exp==c,傳回值是exp的值。如

if (__builtin_expect (x, 0))      foo ();

這條語句提示編譯器我們並不想調用foo(),因為我們期望x==0,編譯器可以據此來最佳化代碼。

Linux核心定義了兩個宏來使用這一特性(見$KERNEL_SRC$/linux/include/linux/compiler.h):

#define likely(x)__builtin_expect(!!(x), 1)#define unlikely(x)__builtin_expect(!!(x), 0)

這兩個宏可以望文生義,下面是個例子:

x = 5;if(likely(x, 1)) { /*提示編譯器執行x++分支的可能性很大*/     x++;}
4. inline

將函式宣告為inline是建議Gcc在處理對該函數的調用時產生更加快速的代碼,Gcc可以將該函數的代碼在其調用者內展開,從而避免了函數調用的開銷。需要注意的是,inline只是建議而已,不能強制Gcc進行展開處理。inline通常與static關鍵字一起使用,其含義就是static與inline的組合,即(1)局部於編譯單元,即函數只能在其定義所在的.c源檔案中使用;(2)inline屬性,即建議Gcc在調用處展開。通常在需要引用函數地址和不能展開(如遞迴函式)的場合,Gcc不做展開處理,而像普通函數一樣為inline函數產生獨立的彙編代碼。

這裡有一篇關於Gcc中inline關鍵字的詳細介紹:http://xushouze2006.blog.163.com/blog/static/16230032200831710196672/。

6. __builtin_prefetch

這個Gcc內建函數的聲明如下

void __builtin_prefetch (const void *addr, ...)

其作用是在訪問資料前資料移到Cache中,以避免Cache未命中產生的延遲。可以在資料即將被訪問前插入這個函數調用,若目標平台支援,Gcc就可以產生資料預取指令。

addr參數指明預取資料的記憶體位址。另外還有兩個選擇性參數rwlocalityrw值為編譯時間常量0或1,0表明為寫操作預取;1為預設值,表明為讀操作預取。locality取值為0-3,0意味著資料沒有時間局部性,可以在訪問後即從Cache中移除,3表明資料的時間局部性很強,在訪問後應該儲存在所有的Cache當中,1和2則分別表明較低和中等的時間局部性,預設值是3。


未完待續……

參考資料:

1.Gcc官方關於C擴充的介紹http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/C-Extensions.html#C-Extensions

2.Linux 核心中的 GCC 特性http://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/

3.Gcc官方關於內建擴充函數的介紹http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

4.Gcc中inline關鍵字http://xushouze2006.blog.163.com/blog/static/16230032200831710196672/

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.