C中的三元运算符?

时间:2018-07-31 06:12:52

标签: c

为什么输出显示为3?这背后的概念是什么?

#include <stdio.h>

int main()
{
    int a = 5, b = 4, c;
    c = a > b ? 1, 2, 3 : 2, 5, 6;
    printf("%d\n", c);
    return 0;
}

3 个答案:

答案 0 :(得分:7)

包含三元运算符的代码行错综复杂。它在解释方式上也具有微妙但至关重要的不对称性,如问题所示,它在编写时远非显而易见。让我们考虑一下原始代码的一个较小变体,如下所示,它同时行使三元运算符的“ true”和“ false”部分(在两个单独的语句中,尽管我可以创建一个函数并将参数传递给它): / p>

#include <stdio.h>

int main(void)
{
    int a = 5, b = 4, c;
    c = a > b ? 1, 2, 3 : 2, 5, 6;
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    a = b - 1;
    c = a > b ? 1, 2, 3 : 2, 5, 6;
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    return 0;
}

该程序的输出为:

a = 5, b = 4, c = 3
a = 3, b = 4, c = 2

这是怎么回事?

请记住,逗号运算符的优先级甚至低于赋值运算符的优先级,因此,您可以根据需要编写以下代码:

if (a > b)
    c = 2, d = 3, e = 6;

if语句的主体中有三个分配。那将不被认为是通用的好代码,但是该技术可以在宏中有用-偶尔在宏中也可以有用。

让我们添加一些括号-编译器解释代码时正确的括号集合:

 c =  a > b  ?  1, 2, 3  : 2 , 5, 6;
(c = (a > b) ? (1, 2, 3) : 2), 5, 6;

条件a > b控制是否对1, 2, 32进行求值,并将结果分配给c1, 2, 3的结果为3,因此,如果为a > b,则分配的值为3(如问题中所示);如果为a <= b,则分配的值为是2。对56进行了副作用评估-但是没有副作用,因此可以有效地将其丢弃。

三元运算符的:?:之间的代码进行分组,这在:之后不会发生。

请注意,要编译此代码,我必须放弃默认的编译器选项。使用问题中的代码以及正常的默认编译器选项,我得到了(top67.c中的源代码):

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \
>     top67.c -o top67 
top67.c:3:5: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
 int main()
     ^~~~
top67.c: In function ‘main’:
top67.c:6:18: error: left-hand operand of comma expression has no effect [-Werror=unused-value]
     c = a > b ? 1, 2, 3 : 2, 5, 6;
                  ^
top67.c:6:21: error: left-hand operand of comma expression has no effect [-Werror=unused-value]
     c = a > b ? 1, 2, 3 : 2, 5, 6;
                     ^
top67.c:6:28: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
     c = a > b ? 1, 2, 3 : 2, 5, 6;
                            ^
top67.c:6:31: error: right-hand operand of comma expression has no effect [-Werror=unused-value]
     c = a > b ? 1, 2, 3 : 2, 5, 6;
                               ^
cc1: all warnings being treated as errors
$

我将从此答案中显示的代码中得到更多错误。您应该使用类似的选项进行编译,以避免您自己的代码出现问题。

答案 1 :(得分:1)

此代码:

c = a > b ? 1, 2, 3 : 2, 5, 6;

被编译器理解为:

(c = a > b ? (1, 2, 3) : 2),
5,
6;
  

在C和C ++编程语言中,逗号运算符   (由令牌表示)是一个二进制运算符,用于评估其   第一个操作数并丢弃结果,然后求值第​​二个   操作数并返回此值(和类型)。   如果有两个以上的操作数,将返回最后一个表达式。

在这种情况下(c = a > b ? (1, 2, 3) : 2)

a > b将返回true

因此它将评估第一个操作数1并丢弃结果,然后评估第二个操作数2并丢弃结果然后评估第三个操作数3并返回其值为{{ 1}}

,然后3在评估它们后将被丢弃,因为它们不会产生任何副作用。

最后,程序的输出为5, 6;

但是如果我们考虑在条件3下使用a < b

在这种情况下,它将评估其他条件并返回其值为(c = a < b ? (1, 2, 3) : 2)

2也将在评估后丢弃,因为它们不会产生任何副作用。

最后,程序的输出为5, 6;

答案 2 :(得分:0)

如果(a> b)

c的值= :令牌之前的期望整数表达式

其他

c的值= :令牌后的期望整数表达式

如果c是整数类型,并且我们正在使用三元运算符?然后编译器期望:令牌前后的整数数据类型

如果我们使用无符号整数数据类型,它将转换为有符号整数数据类型