【问题标题】:Why doesn't GCC's ternary extension support assignment?为什么GCC的三元扩展不支持赋值?
【发布时间】:2013-05-31 07:08:16
【问题描述】:

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 运算符的规范(+-*/%|&^) ,为什么三元扩展运算符不是这样:

int x = ...;
x ?:= 2; // error: Expected expression before '=' token

// which would expand to
x = x ?: 2;

在标准 C 中支持这一点的唯一运算符是逻辑运算符(||&&),绝对三元不属于这些运算符,为什么不能?我们不这样做吗?

我真的很想在我的代码中制作一个带有酷发型的笑脸,但我做不到!这是设计操作员时的疏忽,还是故意并记录在某处?这是运算符短路其操作数的结果,还是完全其他原因?

【问题讨论】:

  • 不确定x ?:= 2; 是什么意思,但可能是x ?= ValueWhenXTrue:ValueWhenXFalse;
  • 我看不出这个问题“没有建设性”。它完全符合主题,讨论了 GNU C 中特定运算符的行为。它被正确标记,给出了简单、具体的例子,并且有一个明确的答案。
  • @chux 用人类的话说就是if x is zero, set it to 2
  • x ?:= 2 的语义是什么?在表达式中:a = x ? b : c,有四个操作数,在扩展 a = x ?: b 中有三个,在你的提案 a ?:= b 中只有两个 - 分配的值和要分配的值,但没有条件 - 你使它变得毫无意义——没有合理的语义解释。
  • @Clifford 条件将是您分配给的左值。

标签: c gcc ternary-operator gcc-extensions


【解决方案1】:

要回答这个问题,我相信还有一些其他的问题需要回答。

为什么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 也没有真正提到为什么需要 ?: 运算符。它主要只是说明操作员的行为在新标准中有所改变:

条件中间操作数的句法限制 运营商已经放宽,不仅包括 逻辑或表达式:几个现存的实现已经采用 这种做法。

条件运算符表达式的类型可以是 void,a 结构或工会;大多数其他运营商不处理此类 类型。在指针和整数之间平衡类型的规则有, 然而,被收紧了,因为现在只有常数 0 可以便携 强制指向一个指针。

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

接下来的问题是:

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

这个问题的答案提到here

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

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

然后尝试回答原来的问题:

为什么 GCC 的三元扩展不支持赋值?

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

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

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

【讨论】:

  • 或许不同寻常的是,我们是一致的 ;-) K&R 使用了一个可能比替代方案不太清楚的示例,从而成功地击中了自己的脚。 ?: 确实可以让代码更简洁明了——然而他们的例子不是其中之一!运算符允许在需要控制流的情况下使用表达式 - 这有时很有用。
猜你喜欢
  • 2015-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 1970-01-01
  • 1970-01-01
  • 2011-05-02
相关资源
最近更新 更多