次のように列挙型の平日を定義すると、
enum weekday {
MON,
TUE,
WED,
THU,
FRI,
};
次に、MONはデフォルトで内部的に0、TUEが1、WEDが2に等しくなります...
しかし、このように定義すると:
enum weekday {
MON,
TUE = 0,
WED,
THU,
FRI,
};
次に、MON
とTUE
の両方が0の値を取得します。
システムは内部でMONとTUEをどのように区別しますか?つまり、次のように宣言すると:
enum weekday today = 0;
では、今日はMON
またはTUE
ですか?または、哲学的に言えば、両方ですか?
C列挙型は「実際に」整数です。たまたまそのように実装されているためだけでなく、標準defines列挙型が整数値を持つためです。したがって、today
の値は「本当に」0です。発生したのは、値0に対して2つの異なる名前を作成したことだけです。
「今日は月か火か」に対する答えは「はい」だと思う;-)
列挙型が同じ値に対して複数の名前を持っていると便利な場合があるため、言語はあなたを止めません。例えば:
enum compression_method {
COMP_NONE = 0,
COMP_LOW = 1,
COMP_HIGH = 2,
COMP_BEST = 2,
COMP_FASTEST = 0,
};
2つの異なる列挙定数が同じ整数値を持つことができるのはなぜですか?
N1265 C99標準ドラフト 6.7.2.2/3「列挙指定子」で明示的に許可されているため:
_
=
_で列挙子を使用すると、同じ列挙内の他の値と重複する値を持つ列挙定数が生成される場合があります。
システムは、内部でMONとTUEをどのように区別しますか?
コンパイル時定数(6.6/6 "定数式")であるため、不可能だと思います。結果として、彼らは:
コンパイル後に異なるように変更することはできません
それらを区別するアドレスがありません: Cの列挙値のメモリ位置
コンパイル時定数はアドレスを必要としません。アドレスは変更できないものには役に立たないからです。
GCCは、enumメンバーの使用を、コンパイル時にAssemblyの即時値に単純に置き換えます。考慮してください:
_#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つの変数を区別できます。他の答えを補足するために、特定のenum
の異なる列挙に同じ値を使用することの実用的な例を示します。
enum slots_t {
SLOT_FIRST = 0,
SLOT_LEFTARM = SLOT_FIRST,
SLOT_RIGHTARM = 1,
SLOT_TORSO = 2,
SLOT_LEFTLEG = 3,
SLOT_RIGHTLEG = 4,
SLOT_LAST = SLOT_RIGHTLEG
};
次に、あなたのコードで行うことができます:
for (int i = SLOT_FIRST; i <= SLOT_LAST; ++i) { }
それは哲学的(またはそうではない)
#define ZILCH 0
#define NADA 0
同じ名前の異なる名前を使用することが理にかなっている多くの用途があります。
列挙定数の名前は、実際の値自体ではなく、値の割り当てに使用されます。今日に値0を割り当てると、出力値は0になります。また、はい、MONとTUEの両方の値は0になり、残りの値にはWED = 1 THU = 2などの値が割り当てられます。