【问题标题】:Bizarre use of conditional operator in LinuxLinux 中条件运算符的奇怪使用
【发布时间】:2011-12-10 12:15:47
【问题描述】:

在3.0.4 Linux内核中,mm/filemap.c有这行代码:

retval = retval ?: desc.error;

我尝试使用 gcc -Wall 编译一个类似的最小测试用例,但没有收到任何警告;行为似乎与以下内容相同:

retval = retval ? retval : desc.error;

查看 C99 标准,我无法弄清楚是什么正式描述了这种行为。为什么会这样?

【问题讨论】:

标签: c linux gcc c99


【解决方案1】:

正如其他几个人所说,这是一个 GCC 扩展,不是任何标准的一部分。如果您使用-pedantic 开关,则会收到警告。

这个扩展的在这种情况下并不真正可见,但想象一下如果它是

retval = foo() ?: desc.error;

使用扩展,foo() 只被调用一次。没有它,你必须引入一个临时变量以避免两次调用foo()

【讨论】:

  • 但是 retval = foo(); retval = retval ? retval : desc.error;更好,并且 100% 便携。
  • 我也很喜欢 David Given 的回复,但这个回复澄清了单一评估语义,并告诉我 -pedantic 引起了警告。选择。
  • @akappa:最好避免引入临时变量。这是 GCC 的真正古老的扩展之一,它反映了 GCC 原始开发人员的函数式语言品味。此外,当时所有的局部变量声明都必须在函数的顶部; “混合声明和代码”直到 C99 才成为标准。
  • @Zack 是否有任何文档记录了这种模糊扩展的历史?我有兴趣阅读更多关于它们的信息,但我猜它们都隐藏在 GNU/GCC 开发人员邮件列表中的古老日志中。
  • @Zack:当时可能不是一个糟糕的扩展,但这并不意味着现在不是。
【解决方案2】:

这是一个 gcc 扩展。 x ?: y 等价于x ? x : y --- 参见http://gcc.gnu.org/onlinedocs/gcc/Conditionals.html#Conditionals

是的,我也认为它是邪恶的。

【讨论】:

  • 为什么说它是邪恶的?不可移植,是的,但它具有您无法以任何其他方式获得的效果(请参阅我的回答)。
  • @Zack:这很邪恶,因为它让那些不知道不可移植和不必要的语法的人感到困惑。
  • 这不是邪恶的。它有点等同于 C# 的 ?? 可空类型运算符。
  • @zzzzBov:不知道 GNU 特定的 C 扩展,这就是重点。
  • @zzzzBov:我明白了。我只是想表明我并不认为它是邪恶的本身,但我认为它是邪恶的,因为它是一个让不懂 GNU C 的人感到困惑的扩展。
【解决方案3】:

这是一个名为 Conditionals with Omitted Operands 的 GCC 扩展。省略中间操作数的效果是使用条件的值作为省略的操作数而无需再次对其求值。即使条件是宏也可以安全使用。

【讨论】:

    【解决方案4】:

    这是针对 C 的 gcc 特定扩展,不是标准的。

    【讨论】:

      猜你喜欢
      • 2013-03-13
      • 2011-10-21
      • 2019-11-17
      • 2015-02-01
      • 2011-04-05
      • 2010-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多