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 つの変数をアドレスで区別できます。