Броски имеют в виду разные вещи в зависимости от того, каковы они. Они могут просто быть переименованиями типа данных без изменения в представленных битах (большинство бросков между целочисленными типами, и указатели похожи на это), или преобразования, которые даже не сохраняют длину (такой как между двойным и международным на большинстве компиляторов). Во многих случаях значение броска является просто неуказанным, означая, что компилятор должен сделать что-то разумное, но не должен документировать точно что.
бросок А не должен даже приводить к применимому значению. Что-то как
char * cp;
float * fp;
cp = malloc(100);
fp = (float *)(cp + 1);
почти наверняка приведет к неправильно выровненному указателю на плавание, которое разрушит программу в некоторых системах, если программа попытается использовать его.
Рассмотрим этот код,
#define WIDTH 300
enum econst
{
eWidth=300
};
const int Width=300;
struct sample{};
int main()
{
sample s;
int x = eWidth * s; //error 1
int y = WIDTH * s; //error 2
int z = Width * s; //error 3
return 0;
}
Очевидно, что каждое умножение приводит к ошибке компиляции, , но посмотрите, как GCC генерирует сообщения для каждой ошибки умножения:
prog.cpp: 19: ошибка: нет соответствия для 'operator *' в 'eWidth * s'
prog.cpp: 20: ошибка: нет соответствия для 'operator *' в '300 * s '
prog.cpp: 21: ошибка: нет совпадения для' operator * 'в' Width * s '
В сообщении об ошибке вы не видите макрос WIDTH
который у тебя #defined
, верно? Это потому, что к тому времени, когда GCC делает любую попытку компилировать строку, соответствует второй ошибке, он не видит WIDTH
, все видит только 300, как до того, как GCC компилирует строку, препроцессор уже уже заменил WIDTH
на 300. С другой стороны, ничего подобного не происходит с enum eWidth
и const Width
.
См. Ошибку здесь: http://www.ideone.com/naZ3P
Также прочитайте Item 2 : Prefer consts, enums, and inlines to #defines
из Effective C ++ Скотт Мейерс.
enum
- это постоянная времени компиляции с отладочной информацией без выделения памяти.
const
выделяется с хранилищем, в зависимости от того, оптимизирован ли он компилятором с постоянным распространением.
#define
не имеет выделения памяти.
Компилятор сохраняет информацию перечисления в двоичном виде, когда программа компилируется с определенными параметрами.
Когда переменная имеет тип enum, отладчик может показывать имя enum. Это лучше всего показать на примере:
enum E {
ONE_E = 1,
};
int main(void)
{
enum E e = 1;
return 0;
}
Если вы скомпилируете это с помощью gcc -g
, вы можете попробовать следующее в gdb
:
Reading symbols from test...done.
(gdb) b main
Breakpoint 1 at 0x804839a: file test.c, line 8.
(gdb) run
Starting program: test
Breakpoint 1, main () at test.c:7
7 enum E e = 1;
(gdb) next
9 return 0;
(gdb) print e
$1 = ONE_E
(gdb)
Если вы использовали , у вас не будет правильного типа, чтобы дать e
, и вам придется использовать целое число. В этом случае компилятор напечатает 1
вместо ONE_E
.
Флаг -g
просит gdb добавить отладочную информацию в двоичный файл. Вы даже можете увидеть, что это там, выпуская:
xxd test | grep ONE_E
Я не думаю, что это будет работать во всех архитектурах, однако.
Проверьте следующую статью, хорошее резюме http://www.queryhome.com/26340/define-vs-enum-vs-constant