这个三元条件 ?: 在(Objective)C语法中是否正确?

45

我之前认为这是不可能的,但显然在 Objective-C 中是被允许的:

int a = b ?: c;

所以你看到他们在这里做的是,他们省略了三元表达式的第二部分,这样如果b非零,则使用b作为第二部分。

这很聪明,但据我所知,这违反了K&R C和可能也违反了ANSI C。

如果没有,多年来我一直错过了一个非常聪明的语法技巧...唉!

更新:这是gcc。


哪个编译器?GCC有这个扩展,尽管是一个已弃用的扩展。 - Kerrek SB
更正确的术语是条件运算符。三元只是指它是一个接受3个参数的运算符。 - Pubby
4个回答

83

来源于http://en.wikipedia.org/wiki/%3F%3A

C语言的GNU扩展允许省略第二个操作数,自动使用第一个操作数作为第二个操作数:

a = x ? : y;

该表达式等价于

a = x ? x : y;

但是,如果x是一个表达式,它只会被评估一次。如果评估这个表达式有副作用,这种差异是显著的。


9

这种行为在gccclang中都有定义。如果您正在构建 macOS 或 iOS 代码,没有理由不使用它。

但是,在可移植代码中,我不会轻易使用它,需要仔细考虑。


1

这是一个GNU C扩展。请检查您的编译器设置(查找C风格)。我不确定它是否是Clang的一部分,我能得到的唯一信息在此页面中:

介绍

本文档描述了Clang提供的语言扩展。除了此处列出的语言扩展之外,Clang旨在支持广泛的GCC扩展。有关这些扩展的更多信息,请参阅GCC手册。


1
$ cat > foo.c
#include <stdio.h>

int main(int argc, char **argv)
{
  int b = 2;
  int c = 4;
  int a = b ?: c;
  printf("a: %d\n", a);
  return 0;
}
$ gcc -pedantic -Wall foo.c
foo.c: In function ‘main’:
foo.c:7: warning: ISO C forbids omitting the middle term of a ?: expression

所以,不允许这样做。在这种情况下,gcc发出的是:

$ ./a.out 
a: 2

因此,未定义的行为会执行您在问题中提到的操作,即使您不想依赖它。


2
我不喜欢你在这里使用“未定义”这个词。更好的做法是称其为非标准行为;对于GCC而言,这种行为 已经 被定义了,只是对于ISO C而言没有被定义。这使得它在其他编译器中未被定义且不可移植,但对于GCC而言仍然有定义。 - Steven Fisher
@steven 由于问题是关于C语法是否正确,因此无论编译器如何处理,它在C中是未定义行为,这才是正确的答案。 - user23743

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接