3

私はこのようないくつかのCコードで問題に遭遇しました:

struct SomeType { ...details immaterial... };

static struct SomeType array[] =
{
    { ... },
    ...
    { ... },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

Unixコンパイラー(GCCのさまざまなバージョン、およびAIXとHP-UXのコンパイラー)はすべて、に非常に満足していましたenum。MSVC2005はエラーで異議を唱えましC2056: Illegal Expressionた。MSDNによると、これは「前のエラーのために式が無効だった」ためです。これが報告された唯一のエラーであり、少し驚くべきことです。

ただし、私の質問は次のとおりです。

  1. MSVC 2005は、C89標準を正確に解釈して許可していenumませんか?
  2. Unixコンパイラは、警告なしにこれを許可するのに寛大すぎますか?
  3. C99(またはC2011)は何か違いがありますか?
  4. MSVCのより新しいバージョンはまだ反対していenumますか?

FWIW:許容できる解決策は、次のように変更することでしたenum

static int const ARRAY_SIZE = sizeof(array) / sizeof(array[0]);

非推奨のオプションは面倒です

Michael Burrは、非常に価値のあるいくつかの追加情報を提供し、問題のロックを解除することができました。

コンパイル可能な例(実際の問​​題と同型):

static const char *names[] = { "abc", "def", "ghi" };
enum { NAMES_SIZE = sizeof(names) / sizeof(names[0]) };

static const struct stuff { const char *name; int flags; } array[] =
{
    { "abc", 1 },
    { "def", 2 },
    { "ghi", 3 },
};
enum { ARRAY_SIZE = sizeof(array) / sizeof(array[0]) };

MSVCの正確なバージョン(によって与えられるcl)は次のとおりです。

Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.762 for 80x86

それはマイケルがうまくいくと言っているバージョンです。

そして、私は自分の問題の原因を見つけました。(以下のコマンドラインは、プロジェクト固有のガフ(サンプルコードに必要のない多数の/Dおよび/Iオプション)をすべて削除します。)コンパイル:

cl     /W3 /c /LD /MD /Od aaa.c

そして、上記のコードは正常にコンパイルされます。

cl /Zg /W3 /c /LD /MD /Od aaa.c

これにより、最初に警告が生成されます。

cl : Command line warning D9035 : option 'Zg' has been deprecated and will be removed in a future release

私は1年以上、非推奨のオプションを使用してコンパイルが行われることについて愚痴をこぼしてきましたが、このサブプロジェクトを担当するチームの誰も立ち上がって修正することをいとわなかったので、私はそうするべきではありません—変更されようとしている何か。

そしてそれは言う:

aaa.c(2) : error C2056: illegal expression
aaa.c(10) : error C2056: illegal expression

そのため、この/Zgオプションは非推奨になるだけでなく、そもそも問題の原因にもなります。今、私は人々を追いかけるためのより良い弾薬を持っています!

マイケル、追加情報をありがとう。

PS:MSDNページに/Zgは次のように書かれています。

このオプションを使用し、プログラムに、、、またはタイプ(またはそのようなタイプへのポインター)/Zgを持つ仮パラメーターが含まれているstruct場合、各、、、またはタイプの宣言にはタグ(名前)が必要です。enumunionstructenumunion

それは完全に正確ではありません。サンプルフラグメントには正式なパラメータはなく、enum値が関数に渡されることはありませんでした。ただし、にタグがない場合でも、フラグenumとともにエラーが表示されます。/Zg


(いいえ。私はMSVC 2005に特に執着していません。私が働いているグループは、まだ最近のものにアップグレードされていません。ほとんどの場合、影響はありません。このように、非常に痛い場合があります。ある日、Windows上の他のビルドが受け入れているように見える理由を解明しenumます。この特定のサブ製品が他のすべてのものと一致せず、他の製品が使用するよりも古いコンパイラを使用していることに気付くのではないかと心配しています。 )。

これは厳密にはCコードです。MSVCタグは、Visual-C++タグの同義語です。

4

1 に答える 1

2

C89では確かに合法です(結果の配列サイズがとして表現できる限りint)。

列挙定数の定義値に関する§3.5.2.2の制約は次のとおりです。

列挙定数の値を定義する式は、intとして表現可能な値を持つ整数定数式でなければなりません。

§3.4では、積分定数式について説明しています。

制約

定数式には、sizeof演算子のオペランド内に含まれている場合を除き、代入、インクリメント、デクリメント、関数呼び出し、またはコンマ演算子を含めることはできません。

各定数式は、そのタイプの表現可能な値の範囲内にある定数に評価されるものとします。

セマンティクス

定数に評価される式は、いくつかのコンテキストで必要です。式が変換環境で評価される場合、算術精度と範囲は、少なくとも式が実行環境で評価されている場合と同じくらい大きくなければなりません。

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

于 2012-03-27T06:08:24.423 に答える