web-dev-qa-db-ja.com

これは三項条件付きですか?:正しい(目的)C構文ですか?

私はこれが可能だとは思っていませんでしたが、明らかにObjective Cでは許可されています。

int a = b ?: c;

つまり、ここで彼らが何をしているのかがわかります。彼らは三項式の2番目の部分を省略しているため、bがゼロ以外の場合、bは2番目の部分として使用されます。

それは賢いですが、私の知る限り、これはK&R C、そしておそらくANSI Cに反しています。

そうでない場合、私は何年もの間、ひどく巧妙な構文のトリックを見逃してきました...

アップデート:gccです。

41
user945620

から http://en.wikipedia.org/wiki/%3F%3A

A GNU Cの拡張により、2番目のオペランドを省略でき、暗黙的に最初のオペランドを2番目のオペランドとして使用することもできます。

a = x ? : y;

式は次と同等です

a = x ? x : y;

ただし、xが式の場合、評価されるのは1回だけです。式の評価に副作用がある場合、違いは重要です。

73

この動作は、gccclangの両方に定義されています。 macOSまたはiOSコードをビルドしている場合、それを使用する理由はありませんnot

ただし、慎重に検討せずに、移植可能なコードで使用することはありません。

7
Steven Fisher

これは GNU C拡張 です。コンパイラの設定を確認します(Cフレーバーを探します)。それがClangの一部であるかどうかはわかりませんが、私が取得できる唯一の情報は このページ にあります:

前書き

このドキュメントでは、Clangによって提供される言語拡張について説明します。ここにリストされている言語拡張に加えて、Clangは広範囲のGCC拡張をサポートすることを目指しています。これらの拡張機能の詳細については、GCCマニュアルを参照してください。

1
sidyll
$ 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

したがって、未定義の動作は、あなたがそれを当てにしたくないとしても、あなたが質問で言うことを実行しています。

1
user23743