2016-01-13 101 views
1

通過退休的工程師代碼排序,我遇到了一個相當簡單的宏,但我的C知識並不是很好。類型鑄造指針解除引用

#define mem32(addr) (*(unsigned long volatile *)(addr)) 
  1. 我是否正確這個調用類型轉換指針引用?
  2. 它類型轉換addr然後解除它?或者相反呢?有關係嗎?
  3. 命令對於類型限定符和類型說明符是否重要?我曾經假設(在此之前)類型限定符必須位於類型說明符之前,但不一定如此
  4. 語法問題。第二個*的目的是什麼?

回答

1
  1. 我是否正確這個調用類型轉換指針引用?

是的。

  1. 它類型轉換爲addr,然後取消它的權限?或者相反呢?有關係嗎?

*(unsigned long volatile *)(addr)是類型轉換addr然後解除引用它。

  1. 命令對於類型限定符和類型說明符是否重要?

號順序並不重要。 C11部§6.7.2/ 2

[...]可以以任何順序發生的類型說明符,可能 與其他聲明說明符混合。 [...]

+0

謝謝。在volatile類型限定符之後的*怎麼樣?我以前見過,但不明白它的目的。 –

+0

'unsigned long volatile *'是類型*指向'unsigned long volatile int' *的指針的說明符。 – haccks

1

演員表(unsigned long volatile *)(addr)發生在取消引用之前。

不,的單詞的順序unsignedlongvolatile不要緊只要沒有進一步的操作員都混合。 I. e。 volatile int*int volatile*是一樣的,但int * volatile是不同的。

在高層次上,這個宏的目的是取任何指針,並從該內存地址讀取前四個字節。

然而,這調用不確定的行爲如果這是傳遞給mem32指針既不是一個指向longchar!這是由於嚴格的鋸齒規則。以前的編譯器曾經爲這個宏安全地生成了預期的代碼,但是如果現代編譯器證明類型不匹配,現代編譯器可能只是使用該宏來優化代碼。所以,不要在新代碼中使用它。