为什么GCC的三元扩展不支持分配?

GCC有一个令人敬畏的三元表达式扩展到C ,它允许我们创建这样的语句:

int x = some_var ?: 10; // expands to some_var ? some_var : 10 

这真的很好,虽然它不是特别直观,但确实有效。 C语言中的大多数二元运算符都有一个与之关联的附加运算符,允许赋值:

 x = x + 2; // instead, we can say x += 2; 

由于这种情况,以及大多数二进制C运算符( +-*/%|&^ )的范数,为什么不是三元扩展运算符的情况:

 int x = ...; x ?:= 2; // error: Expected expression before '=' token // which would expand to x = x ?: 2; 

在标准C中唯一支持此操作符的运算符是逻辑运算符( ||&& ),它们绝对不属于三元组,所以为什么我们不能这样做呢?

在我的代码中,我真的想用一个很酷的头发做一个笑脸,但我不能! 这是对设计操作员的疏忽,还是故意的并且在某处记录? 这是运营商将其操作数短路还是完全不同的结果?

为了回答这个问题,我认为还有一些其他问题需要回答。

为什么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并没有真正提到为什么需要?:运算符。 它主要表明运算符的行为在新标准中已经改变:

对条件运算符的中间操作数的句法限制已经放宽,不仅包括逻辑OR表达式:现有的几种实现都采用了这种做法。

条件运算符表达式的类型可以是void,结构或联合; 大多数其他运营商不处理此类型。 然而,在指针和整数之间平衡类型的规则已经收紧,因为现在只有常量0可以被强制转换为指针。

因此,如果某人有对结构或联合类型执行算术的冲动,那么?:应该比if-else更方便。 我认为没有明显的好处,但至少这是运营商存在的一些原因。

接下来的问题是:

为什么GCC编译器中的?:操作数有编译器扩展?

这里提到了答案:

当它变得有用时是第一个操作数,或者可能(如果它是一个宏参数),包含副作用。 然后在中间重复操作数将执行两次副作用。 省略中间操作数使用已经计算的值而没有重新计算它的不良影响。

因此,这个GCC扩展与可读性或语言一致性无关,它只是为了避免不必要的副作用而添加。

然后尝试回答原始问题:

为什么GCC的三元扩展不支持分配?

可能是因为在赋值条件下访问左值通常不会产生任何不需要的副作用。 x = x ? : 2; 如果x被声明为volatile则只会产生不必要的副作用 – 读取volatile变量是副作用。 所以我能用x ?:= 2;看到唯一的实际用途x ?:= 2; 将阻止某人在同一条件表达式中两次访问相同的volatile变量。

这是一个非常狭窄且价值有限的特征。 它可能在某些特殊的嵌入式系统情况下非常有用,在这种情况下,您在要求苛刻的实时系统中读取硬件寄存器……除此之外,我认为没有用处。

除了传统和主观编码风格偏好之外,我也找不到任何官方或规范来源说明?:运算符本身的任何用途。