簡體   English   中英

算術表達式上下文中的宏擴展?

[英]Macro expansion in context of arithmetic expression?

我在網站上看到了以下代碼。 我無法判斷結果如何變為11 ,而不是2513

為什么我在想25因為SQ(5) 5*5

13因為

SQ(2) = 4;

SQ(3) = 9;

可能是最終結果將是13 (9 + 4)但是驚訝地看到結果為11 結果如何成為11

using namespace std;
#define SQ(a) (a*a)
int main()
{
    int ans = SQ(2 + 3);
    cout << ans << endl;
system("pause");
}

預處理器在源代碼上執行簡單的文本替換。 它對基礎語言或其規則一無所知。

在您的示例中, SQ(2 + 3)擴展為(2 + 3*2 + 3) ,其值為11

定義SQ更健壯的方法是:

#define SQ(a) ((a)*(a))

現在, SQ(2 + 3)將擴展為((2 + 3)*(2 + 3)) ,得到25

雖然這個定義是一種改進,但它仍然不是防彈的。 如果將SQ()應用於具有副作用的表達式,則可能會產生不良后果。 例如:

  • 如果f()是一個向控制台輸出內容並返回int的函數,則SQ(f())將導致輸出被打印兩次。
  • 如果iint變量,則SQ(i++)導致未定義的行為

有關宏的困難的更多示例,請參閱宏陷阱

由於這些原因,通常優選使用函數而不是宏。

#define擴展在編譯器看到源代碼之前啟動。 這就是為什么它們被稱為預處理器指令 ,這里的處理器是將C轉換為機器可讀代碼的編譯器。

所以,這就是宏預處理器傳遞給編譯器的原因:

SQ(2 + 3)擴展為(2 + 3*2 + 3)

所以,這真的是2 + 6 + 3 = 11

你怎么能讓它做你期望的?

  1. 強制執行評估順序。 在宏定義或宏調用中使用()。 要么
  2. 寫一個簡單的功能來完成這項工作

C預處理器在編譯器解釋表達式和C語法之前進行文本替換。 因此,在此代碼上運行C預處理器會轉換:

SQ(2 + 3)

成:

2 + 3*2 + 3

這簡化為:

2 + 6 + 3

這是11。

它只是在編譯之前的替代品

所以你應該試試這個:

#define SQ(a) ((a)*(a))

在您的情況下, SQ(2 + 3)相當於(2+3*2+3) ,即11

但正如我在上面所寫的那樣糾正它,它會像((2+3)*(2+3)) ,即5*5 = 25 ,這就是你想要的答案。

#define preprocesor

語法: #define identifier replacement

  1. 當預處理器遇到此指令時,它會替換替換代碼中其余代碼中的任何標識符。
  2. 這種替換可以是表達,陳述,塊或簡單的任何東西。
  3. 預處理器不理解C,它只是通過替換替換任何出現的標識符。

#define也可以使用參數來定義函數宏:

# define SQ(a) (a*a)

將在編譯時用* a替換任何SQ(a)的出現。 因此,

SQ(2 + 3)將被替換為2 + 3 * 2 + 3在更換完成后執行計算。 因此回答2 + 3 * 2 + 3 = 11

對於您的實現,該值將擴展為2+3 * 2+3 ,這將導致2 + 6 + 3 = 11。

您應該將其定義為:

#define SQ(x) ({typeof(x) y=x; y*y;})

測試gcc ,輸入如

  1. 常量,
  2. 變量,
  3. 不變+常量
  4. 常量+可變
  5. 變量++ / ++變量
  6. 函數調用,包含printf。

注意: typeof是標准C的GNU添加。可能在某些編譯器中不可用。

暫無
暫無

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

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