9

Cは、少なくとも3つのレベルの「定数式」を定義します。

  • 定数式(修飾なし)
  • 算術定数式
  • 整数定数式

6.6パラグラフ3は次のように述べています。

定数式には、評価されない部分式に含まれている場合を除き、代入、インクリメント、デクリメント、関数呼び出し、またはコンマ演算子を含めることはできません。

それで、これは1,2定数式ではないという意味ですか?

パラグラフ8は次のように述べています。

算術定数式は、算術型を持ち、整数定数、浮動定数、列挙定数、文字定数、および式のサイズであるオペランドのみを持つものとします。算術定数式のキャスト演算子は、結果が整数定数であるsizeof演算子へのオペランドの一部を除いて、算術型を算術型に変換するだけです。

のオペランドは何(union { uint32_t i; float f; }){ 1 }.fですか?がオペランドの場合1、これはおそらく算術定数式です{ 1 }が、がオペランドの場合、明らかにそうではありません。

編集:別の興味深い観察:7.17段落3では、結果がoffsetof型の整数定数式である必要がありますが、私が知る限り、size_tの標準実装は、標準による整数定数式である必要はありません。offsetofもちろん、これは、実装が(6.6段落10の下で)他の形式の定数式を受け入れること、またはポインター減算ではなくoffsetofマクロを実装することを許可されているため、問題ありません。__builtin_offsetofただし、この観察の本質はoffsetof、整数定数式が必要なコンテキストで使用する場合は、実装によって提供されるマクロを使用する必要があり、独自のマクロをロールする必要がないということです。

4

2 に答える 2

2

あなたの読書に基づいて、1,2は一定の表現ではありません。なぜそうではないのかわかりませんが、そうではないことに同意します(おそらくそうあるべきであるという事実にもかかわらず)。

6.5.2は、複合リテラルを接尾辞演算子として指定します。だからで

(union { uint32_t i; float f; }){ 1 }.f

オペランドはと(union { uint32_t i; float f; }){ 1 }演算子です。最初の引数は型であるため、算術定数式ではありませんが、定数式です。f.union

更新:私はこれを標準の異なる解釈に基づいていました。

私の以前の推論は(union { uint32_t i; float f; }){ 1 }.f、定数式の基準を満たしているため、定数式であるというものでした。それでも定数式(6.6段落3)の基準を満たしていると思いますが、標準タイプの定数式(整数、算術、アドレス)のいずれでもないため、6.6段落までの定数式の対象となるだけです。 10。これにより、実装定義の定数式が可能になります。

私もあなたの編集に取り掛かるつもりでした。の「ハック」実装は定数式であると主張するつもりでしoffsetofたが、上記と同じだと思います。定数式(および場合によってはアドレス定数)の基準を満たしていますが、整数定数式ではありません。したがって、6.6段落10以外では無効です。

于 2011-02-04T00:48:07.213 に答える
1

定数式の場合1,2、次のようなコードをコンパイルできます。

{ // code        // How the compiler interprets:
  int a[10, 10]; // int a[10];

  a[5, 8] = 42;  // a[8] = 42;
}

それが本当の理由かどうかはわかりませんが、この(よくある?)間違いに対してエラーを出すことは1,2、定数式に変えるよりも重要であると考えられていたと思います。

更新:R。がコメントで指摘しているように、VLAの導入以来、コードについてのコードはコンパイラエラーではなくなりました。

于 2011-02-04T05:58:49.920 に答える