55

次のように列挙型の平日を定義した場合、私はそれを知っています:

enum weekday {
    MON,
    TUE,
    WED,
    THU,
    FRI,
};

次に、MON はデフォルトで内部的に 0 に等しくなり、TUE は 1 に、WED は 2 に...

しかし、このように定義すると:

enum weekday {
    MON,
    TUE = 0,
    WED,
    THU,
    FRI,
};

次に、両方ともMON0TUEの値を取得します。

システムは、MON と TUE を内部的にどのように区別しますか? つまり、次のように宣言すると:

enum weekday today = 0;

じゃあ今日MONTUE?それとも、哲学的に言えば、両方ですか?

4

5 に答える 5

84

Cの列挙型は「実際に」整数です。これは、そのように実装されているだけでなく、標準で列挙型が整数値を持つように定義されているためです。したがって、の値todayは「本当に」0です。発生したのは、値0に2つの異なる名前を作成したことだけです。

それなら、「今日は月か火か」に対する答えは「はい」だと思います;-)

列挙型が同じ値に対して複数の名前を持つと便利な場合があるため、この言語はあなたを止めません。例えば:

enum compression_method {
    COMP_NONE = 0,
    COMP_LOW = 1,
    COMP_HIGH = 2,
    COMP_BEST = 2,
    COMP_FASTEST = 0,
};
于 2012-07-10T11:46:27.420 に答える
22

2 つの異なる列挙定数が同じ整数値を持つことができるのはなぜですか?

これは、 N1265 C99 標準ドラフトの 6.7.2.2/3「列挙指定子」で明示的に許可されているためです。

で列挙子を使用すると=、同じ列挙内の他の値と重複する値を持つ列挙定数が生成される場合があります。

システムは、MON と TUE を内部的にどのように区別しますか?

コンパイル時定数なので無理だと思います(6.6/6「定数式」)。結果として、彼らは:

  • コンパイル後に異なるように変更することはできません

  • それらを区別するアドレスがありません: C の列挙値のメモリ位置

    アドレスは変更できないものには役に立たないため、コンパイル時定数にはアドレスは必要ありません。

GCC は、コンパイル時に列挙型メンバーの使用をアセンブリ内の即時値に単純に置き換えます。検討:

#include <stdio.h>

enum E {
    E0 = 0x1234,
    E1 = 0x1234
};
int i = 0x5678;

int main() {
    printf("%d\n", E0);
    printf("%d\n", E1);
    printf("%d\n", i);
    return 0;
}

GCC 4.8 x86_64 でコンパイルおよび逆コンパイルします。

gcc -c -g -O0 -std=c89 main.c
objdump -Sr main.o

出力には次が含まれます。

    printf("%d\n", E0);
   4:       be 34 12 00 00          mov    $0x1234,%esi
  ...
    printf("%d\n", E1);
  18:       be 34 12 00 00          mov    $0x1234,%esi
  ...
    printf("%d\n", i);
  2c:       8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 32 <main+0x32>
                    2e: R_X86_64_PC32       i-0x4
  32:       89 c6                   mov    %eax,%esi

したがって、次のことがわかります。

  • 列挙型メンバーは即時型として使用される$0x1234ため、それらがどこから来たのかを知ることは不可能です
  • ただし、変数iはメモリから取得0x0(%rip)されるため (再配置される)、2 つの変数をアドレスで区別できます。
于 2015-06-18T13:15:49.887 に答える
8

それは哲学的です(またはそうではありません)

#define ZILCH 0
#define NADA  0

異なる名前を同じ番号にすることが理にかなっている用途はたくさんあります。

于 2014-06-16T11:02:28.420 に答える
2

列挙定数の名前は、実際の値自体ではなく、値を割り当てるために使用されます。今日に値0を割り当てると、出力値は0になります。はい、MONとTUEの両方に値0が割り当てられ、残りの値にはWED = 1 THU=2などが割り当てられます。

于 2012-07-10T12:02:17.623 に答える