为什么输出显示为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;
}
答案 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, 3
或2
进行求值,并将结果分配给c
。 1, 2, 3
的结果为3
,因此,如果为a > b
,则分配的值为3
(如问题中所示);如果为a <= b
,则分配的值为是2
。对5
和6
进行了副作用评估-但是没有副作用,因此可以有效地将其丢弃。
三元运算符的:
对?
和:
之间的代码进行分组,这在:
之后不会发生。
请注意,要编译此代码,我必须放弃默认的编译器选项。使用问题中的代码以及正常的默认编译器选项,我得到了(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是整数类型,并且我们正在使用三元运算符?然后编译器期望:
令牌前后的整数数据类型
如果我们使用无符号整数数据类型,它将转换为有符号整数数据类型