2013-05-17 59 views
4

最近碰到下面的例子,它返回一個寄存器讀取__ret但沒有return語句功能像宏返回一個值

#define READWORD(offset)  ({ \ 
       unsigned short __ret=0;\ 
       __ret = readw(offset);\ 
       __ret; \ 
       }) 

難道在同谷歌和發現像宏函數可以返回值。假設上一條語句「_ ret」相當於返回一個值是否安全? 如果我在「 _ret」後改變了__ret值,我又有了什麼陳述。哪一個會返回?

+0

可能重複[可以將範圍包裝在圓括號中並在C中返回一個值?](http://stackoverflow.com/questions/16571112/can-scopes-be-wrapped-in-parentheses-and-return- a-value-in-c) –

回答

8

這是使用名爲Statement Expressions的GCC擴展。

除非您需要移植到GCC(和Clang/LLVM)以外的編譯器,否則您可以使用它。

+0

這是我從鏈接中選擇的內容「複合語句中的最後一項應該是一個表達式,後跟分號;此子表達式的值用作整個構造的值。如果在花括號中最後使用了其他類型的語句,那麼該構造的類型爲void,因此實際上沒有值。)「據我所知,最後一條語句是宏的整個計算值。糾正我,如果我錯了 – pkumarn

+0

這是正確的......在這個例子中,我不知道語句表達式的好處與'#define READWORD(offset)((unsigned short)readw(offset))'比較是便攜式的並且執行相同的工作AFAICS。一般來說,在Statement Expressions中你可以做的事情是你不能沒有的。 –

3

讓我們來分析一下。例如,讓我們看看READWORD(1)會做什麼。預處理器將插入此: ( { 無符號短__ret = 0; __ret = readw(1); __ret; } )

現在,我們可以看到它的最高。我們只是用參數(1)調用函數readw並將其分配給一個未簽名的short。之後,我們只需要__ret;雖然它是一個完全有效的陳述,但它並沒有出現任何問題。但請繼續閱讀!

一切超出了最後的範圍}。

但是,封閉()使所有的區別。優雅地說,整個事物是一個表達式,它具有值__ret。所以你可以給它分配一個變量。這使得整個事情在宏觀論證中非常穩定。

這有助於取消嗎?

+0

您已經省略了擴展文本週圍的括號。它是標準C的GCC特定擴展;除了Clang/LLVM(部分基於GCC)之外,它不可移植。 –

+0

糟糕。把它放進去!我從來不會在實踐中使用它,因爲它是一個過於成熟的習慣用法,並且會使源代碼管理維護者感到困惑。我的意思是,我的解釋很混亂,不是嗎? – Bathsheba