Объект, объявленный с const
, не является константой (точнее, его имя не является константным выражением).Ключевое слово const
не означает «постоянный», оно означает «только для чтения».Поэтому, учитывая:
const int answer = 42;
printf("The answer is %d\n", answer);
, в принципе, для оценки вызова printf
необходимо извлечь значение answer
из хранилища, прежде чем передать его в функцию printf
.
Нона самом деле, любой компилятор, который стоит того, за что вы платите (даже если он бесплатный), оптимизирует ссылку на answer
, так что вызов printf приводит к тому же машинному коду, что и
printf("The answer is %d\n", 42);
(gcc делаетэто с -O1
или лучше. Если вы не укажете -O...
, тогда код фактически извлекает значение объекта - но тогда, если вы не запрашиваете оптимизацию, вы говорите компилятору, что неочень заботится о производительности.)
(Действительно умный компилятор может сгенерировать код, эквивалентный
puts("The answer is 42");
.)
Реальное отличие состоит в том, что имя answer
не можетиспользоваться в контекстах, которые требуют постоянного выражения.Например, case answer: ...
было бы допустимо в C ++, но недопустимо в C.
Обратите внимание, что int arr[answer];
действительно допустимо, по крайней мере, в C99, что позволяет использовать массивы переменной длины.Это было бы в равной степени законно, если бы вы написали
const int answer = rand() % 100 + 1;
Но VLA могут иметь только автоматическую продолжительность хранения, поэтому они не могут быть объявлены в области видимости файла или с ключевым словом static
.
Asдля трюка enum
:
enum { answer = 42; }
, который делает answer
константным выражением, но он ограничен значениями типа int
(константы перечисления C всегда имеют тип int
).Некоторые могут утверждать, что это злоупотребление функцией enum
.Это так, но я не позволяю этому беспокоить меня.
Так что может будет штрафом за производительность для const int answer = 42;
, а не #define answer 42
, но на практике это простоограничить контексты, в которых вы можете его использовать.