宏替换分配

时间:2016-01-07 19:14:00

标签: c macros

#define MAX(x,y)(x)>(y)?(x):(y)
main()
{
    int i=10,j=5,k=0;
    k==MAX(i++,++j);
    printf("%d %d %d",i,j,k);//11 7 0
}

为什么输出是11 7 0而不是11 6 0?

4 个答案:

答案 0 :(得分:2)

声明扩展为

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

让我们用一些额外的parens重写这一点,以强调在计算优先级规则时如何解析表达式:

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

请注意,>的优先级高于==

现在,首先评估(i++) > (++j),评估为1ij都会增加。然后将k1进行相等性比较,得出0。因此,条件运算符的计算结果为(++j),因此j再次递增。

总计i增加一次,j增加两次,k不会被修改。因此输出就像你描述的那样。

这是使用宏的危险的一个很好的例子。功能真的是你需要的。

其他一些观点:

  1. 您的main声明不正确。它应该是int main(void)
  2. 如果在启用警告的情况下编译,编译器将标记相关行。我的编译器说:
  3. C:\Users\blah\Desktop>gcc main.c -Wall -o main.exe
    main.c: In function 'main':
    main.c:2:20: warning: suggest parentheses around comparison in operand of '==' [-Wparentheses]
     #define MAX(x,y)(x)>(y)?(x):(y)
                        ^
    main.c:6:8: note: in expansion of macro 'MAX'
         k==MAX(i++,++j);
            ^
    

答案 1 :(得分:1)

宏由预处理器替换为三元运算符:

k == (x) > (y) ? (x) : (y)

比较:(x)>(y)将首先完成,并且将产生1,但是那时三元运算符的其余部分将不会被评估,因为运算符==具有优先权。代码相当于:

( k == ( (x) > (y) ) ) ? (x) : (y)

我们必须将结果(1为1)与k:k==(x)>(y)进行比较,得到结果0.然后只评估三元运算符的第三个运算符:(y)。< / p>

总而言之,i将被评估一次,j将被评估两次。因此i的最终结果为11,j的结果为7。 (变量k将保持为0,因为它从未被赋值。)

答案 2 :(得分:0)

使用真实表达式扩展宏:

WSARecv()

这是一个典型的条件表达式。

  • k == (i++) > (++j) ? (i++) : (++j); expr1 ? expr2 : expr3; expr1。这实际上包含两个逻辑操作。由于k == (i++) > (++j)的优先级低于==,因此首先评估此逻辑>,并在第一次逻辑测试之前完成(i++) > (++j)++j现在是6,我们j是真的(10 > 6)。现在来到第二个逻辑1,它评估为false(k == 1)。
  • 由于0为false,因此会expr1进行评估,即expr3,并且++ post-fix再次表示(++j)在评估之前递增。 j现在变为7。

答案 3 :(得分:-2)

宏在定义它们时需要小心,它们不一定按照您期望的方式扩展。 C中宏的一个关键特征是它们实际上执行替换,术语为术语。

这个概念在K&amp; R书中以及在线的多个教程中得到了很好的解释,只是google它。