簡體   English   中英

C,C ++預處理器宏

[英]C, C++ preprocessor macro

任何人都可以解釋這是如何工作的

#define maxMacro(a,b) ( (a) > (b) ) ? (a) : (b) 

inline int maxInline(int a, int b)
{
  return a > b ? a : b;
}

int main()
{  
  int i = 1; j = 2, k = 0;
  k = maxMacro(i,j++); // now i = 1, j = 4 and k = 3, Why ?? Where is it incremented ?
  //reset values
  i = 1; j = 2, k = 0;
  k = maxInline(i,j++); // now i = 1, j = 3, and k = 2, Why ??
  return 0;
}

所以,我想知道j的值到底在哪里增加,同時檢查條件或返回或在調用時?

  • 一種。 使用宏
  • 使用內聯方法

更新:感謝所有人,現在我理解這一點。 但出於好奇,為什么有人會在調用方法時執行j ++,為什么不在調用方法后增加j,這樣就不那么容易混淆了。 我在某個地方看到了這段代碼,所以要問它!

問題是預處理器只是直接替換宏文本。

maxMacro(i, j++)

( (i) > (j++) ) ? (i) : (j++)

如您所見,當j更大時,它會增加兩個增量。

這正是您應該優先選擇內聯函數而不是宏的原因。

k = maxMacro(i,j++);

擴展為:

k = ( (i) > (j++) ) ? (i) : (j++)

由於?:的序列點?:這個行為很明確。 i小於j的初始值時, j遞增兩次並且k接收一次遞增的j值。

(如果i大於j的初始值,那么當評估(i) > (j++)j將僅增加一次, k將被賦予(i)值,並且不執行第二增量。)

在:

k = maxInline(i,j++);

maxInline時調用值ij增量之前(1和2)中,j是在函數調用之前遞增,並且k分配maxInline的返回值(2)。

宏導致文本擴展。 它發生在編譯器甚至考慮表達式和運算符之前,並且在將輸入文本拆分為單個標記之后立即發生。 因此,以下行:

k = maxMacro(i,j++);

宏擴展后完全等效於以下行:

k = ( (i) > (j++) ) ? (i) : (j++);

顯然,這里有兩個增量。

另一方面,內聯函數只是函數,並且就調用而言,與非內聯函數完全相同。 在函數調用中,首先計算參數列表中的表達式,然后將它們的值綁定到函數體內的相應參數名稱。 因此,評估只發生一次。

這就是為什么宏是邪惡的!

在編譯器到達之前,宏是由k = maxMacro(i,j++);文字文本k = maxMacro(i,j++); ,因此k = maxMacro(i,j++); 變成( (i) > (j++) ) ? (i) : (j++); ( (i) > (j++) ) ? (i) : (j++); 我希望你能在這里看到問題。

在(內聯)函數調用中,a和b的值通過值傳遞到函數中,其中i和j的初始值被傳入,之后j遞增。

調用宏與調用函數不同。 預處理器將對maxMacro(i,j ++)的引用替換為看起來像這樣的文本文本。

(i)>(j ++)? (i):( j ++)

后增量運算符使用其目標的當前值,然后遞增其目標。 因此,如果i = 1且j = 2,則會發生以下情況:

(i)>(j ++)// 1與2比較,j增加到3? (i):( j ++)2大於1,因此傳遞“b”值。 再次調用j ++,因此從表達式返回前一個值3,但作為副作用,j增加到4。

另一方面,就如何處理參數變量而言,內聯函數就像非內聯函數一樣工作。
當j ++作為函數調用的一部分放入堆棧時,它被引用一次。 函數調用以ab值2運行並返回其結果(2),而j作為副作用遞增到3。

注意:調用maxInline后,您的問題表示k = 3。 那次電話后我得到了k = 2 - 結果我期待。

我希望這能澄清事情。

ķ

查看CERT C編碼標准:

PRE00-C。 首選內聯或靜態函數來實現類似函數的宏

這是一個很好的資源,關於各種小問題的大量信息,人們應該避免使其代碼干凈,穩定,安全:)

奇怪的。 到目前為止,沒有人提到內聯函數選項是類型安全的,宏不是!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM