GCC有一个awesome ternary expression extension to C,它允许我们创建一个这样的语句:
int x = some_var ?: 10; // expands to some_var ? some_var : 10
哪个非常好,虽然它不是特别直观,但确实有效。 C语言中的大多数二元运算符都有一个与之关联的附加运算符,允许赋值:
x = x + 2;
// instead, we can say
x += 2;
由于这种情况,大多数二元C运算符(+
,-
,*
,/
,%
,{{ 1}},|
,&
),为什么不是三元扩展运算符的情况:
^
在标准C中不支持此操作的唯一运算符是逻辑运算符(int x = ...;
x ?:= 2; // error: Expected expression before '=' token
// which would expand to
x = x ?: 2;
,||
),这绝对是三元不属于的,那我们为什么不能这样做呢?
我真的很想在我的代码中用一个很酷的头发做一个笑脸,但我不能!这是设计操作员的疏忽,还是故意和记录在某处?这是操作员将其操作数短路还是其他东西的结果?
答案 0 :(得分:7)
要回答这个问题,我相信还有其他一些问题需要回答。
为什么C语言中有
?:
运算符,为什么它更好 比if-else
?
据我所知,没有人能够回答这个问题,而不仅仅是陈述自己的主观意见。 K& R 2.11表明
“条件表达式通常会导致简洁的代码。”
然后他们用行
来说明这一点printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');
这是他们自己的主观,泥泞的观点。就个人而言,我相信
printf("%6d", a[i]);
if(i%10==9 || i==n-1)
printf("\n");
else
printf(" ");
因为我可以在10秒内阅读并理解该代码,而不是1分钟阅读和理解K& R版本,所以远远更加清晰。此外,我的代码将整数打印与不相关的格式分开。但当然,这是我的主观意见,没有明显的正确与错误。
至于官方消息来源,C99基本原理版本5.10,6.5.15并未真正提及为什么需要?:运算符。它主要只是指出运营商的行为在新标准中有所改变:
对条件的中间操作数的语法限制 运营商已经放松了包括更多 logical-OR-expression:采用了几种现存的实现方式 这种做法。
条件运算符表达式的类型可以是void,a 结构或联合;大多数其他运营商不处理此类问题 类型。在指针和整数之间平衡类型的规则有, 然而,收紧了,因为现在只有常数0可以 强迫指针。
因此,如果有人要求对struct或union类型执行算术,那么?:应该比if-else更方便。我认为没有明显的好处,但至少这是运营商存在的一些原因。
接下来的问题是:
为什么GCC中的
?:
操作数有编译器扩展 编译器?
提到的答案是here:
当它变得有用时是第一个操作数,或者是(如果它) 是一个宏参数),包含副作用。然后重复 中间的操作数会执行两次副作用。省略 中间操作数使用已经计算过的值而没有 重新计算它的不良后果。
因此,这个GCC扩展与可读性或语言一致性无关,只是为了避免不必要的副作用而添加它。
然后尝试回答原来的问题:
为什么GCC的三元扩展不支持分配?
可能是因为在赋值条件下访问左值通常不会产生任何不必要的副作用。如果x被声明为x = x ? : 2;
,则volatile
只会产生不必要的副作用 - 读取volatile变量是副作用。因此,x ?:= 2;
可以看到的唯一实际用途是阻止某人在同一条件表达式中两次访问相同的volatile变量。
这是一个非常狭窄且价值有限的特征。它可能在某些特殊的嵌入式系统中很有用,在这种情况下,您可以在要求苛刻的实时系统中读取硬件寄存器......除此之外,我认为没有用处。
除了传统和主观编码风格偏好之外,我也找不到任何官方或规范来源说明?:运算符本身的任何用途。