2015-01-07 15 views
7

次のような定義された動作は何ですか? GCCとMSVC両方のコンパイラと私のテストから列挙子と同じ名前の変数

#include <stdio.h> 

typedef enum { 
    ENUM_VAL_1 = 1, 
    ENUM_VAL_2 = 2 
} TEST_ENUM; 

int main() { 
    TEST_ENUM testVar1 = ENUM_VAL_1; 
    TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; 
    TEST_ENUM testVar2 = ENUM_VAL_1; 

    printf("ENUM_VAL_1 = %u\n",ENUM_VAL_1); 
    printf("testVar1 = %u\n",testVar1); 
    printf("testVar2 = %u\n",testVar2); 

    return 0; 
} 

、これの動作はtestVar1は、しかし、次のステートメントは、変数ENUM_VAL_1を設定しようとする列挙値「ENUM_VAL_1」または1に等しく設定されるということですこれは変数ENUM_VAL_1を列挙値ENUM_VAL_1に設定するのではなく、当面は初期化されていないのでガーベジであることに注意してください。もちろん、testVar2は変数ENUM_VAL_1と同じガベージ値を取得します。

Cの標準に従ってこの動作が定義されていますか、それともこの未定義の動作ですか?それが定義されているかどうかにかかわらず、私はこのタイプの例があいまいさのために悪い練習であると推測しています。

ありがとうございます!

+1

word enumeratorをword enumerationに置き換えて、テーマのタイトルを更新する必要があります。 –

答えて

6

C標準(識別子の6.2.1スコープ)によれば

  • ...識別子は、同じ名前空間内の2つの異なるエンティティ、スコープを指定した場合重複する可能性がある。その場合、あるエンティティ (内部スコープ)のスコープは、他の エンティティ(スコープ)のスコープの前で厳密に終了します。 内部スコープ内で、識別子 は、内部スコープで宣言されたエンティティを指定します。外側のスコープ内に と宣言されたエンティティは、内側の スコープ内に隠されており(見えません)
  • そして

    7構造体、共用体、列挙型のタグが タグを宣言型指定子内のタグの出現後だけ を開始スコープを持っています。各列挙定数には、列挙子リスト内にその定義列挙子が表示された直後に始まるスコープがあります。どれ 他の識別子は、 の完成その宣言子

    だから、この宣言で

    TEST_ENUM ENUM_VAL_1 = ENUM_VAL_1; 
    

    宣言子ENUM_VAL_1は、サイン=の前に完了したとみなされた直後に始まり、スコープを持っています。それは列挙子を隠します。

    実際には、それ自体で初期化され、不確定な値を持ちます。

    同じであれば(名前の宣言のポイントは、直ちにその 完全宣言子(8節)の後に、その初期化の前にあるC++(宣言の3.3.2ポイント)

    1に対して有効です)、 を除きます。 [実施例:ここ

    int x = 12; 
    { int x = x; } 
    

    第2のXは、それ自体(不定)値で初期化されます。 -end example]

    +0

    非常に完全で徹底的な回答 - ありがとうございます! –

    3

    私はTEST_ENUM ENUM_VAL_1 = ENUM_VAL_1;行がコンパイルに失敗すると予想しました。私は割り当てられた値をENUM_VAL_2に変更し、ENUM_VAL_1 = 2testVar1 = 1testVar2 = 2を出力したので、ENUM_VAL_1はローカル変数です。

    実際は日常的なスコープの問題です。 main()の変数宣言が—の外側の宣言を覆い、typedefmain()の範囲内にある場合、コードはコンパイルされないことを意味します。コンパイルオプションに-Wshadowを追加すると、シャドウイングが表示されます。 testVar1の設定後、ENUM_VAL_1は、列挙定数ではなくローカル変数を意味します。変数をそれ自身で初期化しても、実際に変数は初期化されません。定義されていないガベージを値にコピーします。

    関連する問題