执行三元运算符

时间:2017-07-02 19:29:12

标签: c macros operator-keyword ternary

#include <stdio.h>

#define max(x,y)(x)>(y)?x:y

int main() {
    int i = 10;
    int j = 5;
    int k = 0;
    k == max(i++, ++j);
    printf("%d%d%d ", i, j, k);
    return 0;
}

我知道答案。这是11 7 0但是怎么样?请帮我执行三元运算符。

3 个答案:

答案 0 :(得分:6)

声明

k==max(i++,++j);  

扩展为

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

请注意,==的{​​{3}}运算符高于?:,因此上述表达式相当于

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

由于(i++)>(j++)将为true,因此k == ((i++)>(j++))被评估为false,因此j++(并且它的值变为{{1} }}将被评估(将跳过7)。

注意:上述表达式不会调用未定义的行为,因为在评估三元运算符的第一个操作数与第二个或第三个操作数之间存在precedence。例如,表达式

i++

有明确的行为。

答案 1 :(得分:2)

这个问题绝对是一个技巧问题,可以吸引许多毫无防备的C程序员。这里的不同响应者在C中有超过100年的复合经验,但是需要多次尝试才能做到这一点:

表达式k == max(i++, ++j);扩展为:

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

将其解析为此(==的优先级低于>,但优先级高于?):

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

三元运算符评估测试(i++)>(++j),对于程序中的值是正确的,因此评估为1,不同于k的值,因此它继续评估第三个表达式j++,它再次递增j并返回中间值6。测试和执行的分支之间有一个序列点,因此可以两次递增j。由于测试评估为假,因此根本不执行第二个分支。

i递增一次,其值变为11

j递增两次,其值为7

上述语句未修改

k,因为==是比较运算符,而不是赋值运算符。

因此输出为11 7 0

备注:

程序使用宏max多次评估其参数,并且它们在扩展中没有正确括号:2个错误说明了宏的缺点。这个宏应该是名称MAX,以强调它的参数不应该有副作用,并且它的扩展应该用这种方式完全括号:

#define MAX(x,y) ((x) > (y) ? (x) : (y))

更好的选择是使其成为内联函数:

static inline int max(int x, int y) {
    return x > y ? x : y;
}

如果程序有此声明:

k = max(i++, ++j);

输出为12 6 11,因为与==不同,=的优先级低于?,因此语句会扩展为:{/ p>

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

您可以学习table of operator precedence for C。在我的拙见中有太多级别,很难记住所有这些,特别是因为其中一些是相当直观的:打印副本并保持方便或制作书签。如有疑问,请使用括号。

答案 2 :(得分:0)

你使用的是双等号,这是一个比较。 k==max(i++,++j);将max的返回值与k进行比较,即0。

相反,请尝试将==更改为=