简体   繁体   中英

Using Nested macros in C

#include "stdafx.h"
#include<stdio.h>

#define PR(x) printf("%d\t",(int)(x));
#define PRINT(a,b,c) PR(a) PR(b) PR(c)
#define MAX(a,b) (a<b?b:a)

int main()
{
    int x=1,y=2;
    //PR(MAX(x++,y));
    PRINT(MAX(x++,y),x,y);  //2,2,2
    PRINT(MAX(x++,y),x,y);  //2,3,2
    return 0;
}

x is 1 so the 3 values to be passed as arguments in PRINT is 2 2 2.

Then in the second PRINT the values that will be passed is 2 3 2. So the output should be 2 2 2 2 3 2. But this program outputs as 2 2 2 3 4 2.

Your MAX macro is bad. It evaluates one of its arguments twice.

 MAX(x++,y)

expands to:

 (x++ < y ? y : x++)
                ^^^

So x is incremented twice if it started out smaller than y .

There is no undefined behavior in that code because there is a sequence point between the evaluation of the first part of the ternary operator and the part that is selected. The whole PRINT expression expands to:

 printf("%d\t", (x++ < y ? y : x++));
 printf("%d\t", (x));
 printf("%d\t", (y));

Which is all fine. This does not mean you should be using such macros. Use simple functions, and let the compiler do its job of type-checking and inlining what it thinks is best.

Your macros have several problems:

  • Never hide a ; inside a macro but have it behave like an ordinary statement
  • Don't write macros that evaluate their arguments multiple times
  • always put parentheses around macro parameters such that you know the precedence of all operators.

Your MAX(x++,y) call translates to (x++<y?y:x++) and results in double modification of x during the first call.

PRINT((MAX(x++,y),x,y) -> PR(MAX(x++,y)) PR(x) PR(y) -> PR(x++

x = 1, y = 2 Does PR(2 since 1<2) and increments x to 2 Then PR(2) PR(2) - Hence output 2 2 2

Next PR(MAX(x++ (ie2) < 2 - false)? 2: x++ (ie use incremented value of x from condition (3) then output 3 and increment x to 4) - hence x gets incremented twice

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM