2015-06-23 3 views
9

const переменные в C++ должны быть инициализированы означает, что uninitialized const variable невозможно & это ошибка компилятора. Но почему это не так же на языке C? Рассмотрим следующую программу, которая отлично компилируется C:Почему переменная const не обязательно должна быть инициализирована в C?

#include <stdio.h> 
int main() 
{ 
    const int a; 
} 

В чем причина, чтобы позволить uninitialized const? Было бы неплохо, если C также следует тому же правилу, что и C++? Это связано с тем, что локальная переменная const должна быть инициализирована каждый раз при вызове функции & для инициализации требуется время?

+0

** Заметка модератора **: Пожалуйста, используйте комментарии для запроса разъяснений/обсуждения заданного вопроса. Спасибо. –

ответ

3

Разница, вероятно, связана, помимо прочего, со значительно более расслабленным подходом к инициализации на языке C вообще, а не только в отношении const объектов. Например, этот код является незаконным в C++

goto over; 
int a = 5; 
over:; 

, потому что он прыгает в сферу a в обход его инициализации. Между тем в C этот код является совершенно законным, с переменной a с неопределенным значением в over:.

Такая же логика применима к вашей декларации const int a. C-язык просто считает, что неинициализированный объект не имеет большого значения, даже в ситуациях, когда более невозможно установить его в определенное значение позже.

Основная причина более строгих требований к инициализации в C++ - введение в язык нетривиальной инициализации (конструкторы), то есть инициализации, которая не может быть осмысленно обойдена. Скалярные объекты и их инициализация на C++ просто помечены как небольшая часть гораздо более широкой концепции.

Было бы неплохо, если C также следует тому же правилу, что и C++?

Я этого не вижу. C и C++ - существенно разные языки. И они относятся к const совсем по-другому.

3

История.

const был указан в C++ с самого начала, а использование соответствует целям этого языка. const был позже указан в C, но с соответствующим, но иным значением, чтобы свести к минимуму проблемы с совместимостью кода C.

Поскольку C начался без const, его более позднее включение больше похоже на модификатор read-only, чем на constant. Это позволило существующим компиляторам существенно лечить const как ничего для записи на const - это неопределенное поведение. Более новые компиляторы/код могли бы воспользоваться тем, что обеспечивает const.

const int a; 
a = 5; // problem in C as code attempts to write `a` 

// Really should be `const char *fred`, but allowed for backwards compatibility. 
char *fred = "sally"; 

C++ принял более сильный подход и требует инициализации.

Смотрите также const in C vs const in C++

0

Я считаю, что причина является условность.

В C, практически не тип объекта не всегда требуется быть инициализирован, и никогда не было требуется для инициализации.

const объекты - это еще один вид объекта с одной специальной характеристикой, зачем делать исключение для них?

1

Потому что C абсолютно уверен в программизме и позволяет ему делать много вещей, в том числе глупых: int *x = NULL; x[4] = 12; будет скомпилирован без ошибок и даже без предупреждений многих компиляторов.

Точнее, const - это просто обещание программиста, что переменная не должна изменяться, и этот компилятор мог бы рассматривать ее как постоянную, если она может помочь в оптимизации. Но компилятор никогда не будет применять какие-либо правила времени выполнения, чтобы запретить изменение значения константы:

const a = 1; 
int *ix = (int *) &a; 
*ix = 2; 
printf("a=%d\n", a); /* UB : could print 1 or 2 */ 

будет составлен без предупреждения. Но он будет вызывать неопределенное поведение, потому что вы изменили объект, объявленный как const.

Я считаю, что инициализация переменных const не допускается просто потому, что текущая спецификация C не запрещает ее! В предыдущих версиях инициализация всегда была необязательной. Возможно, будущие версии могут принудительно инициализировать автоматические переменные.

В любом случае глобальная или статическая константная переменная фактически автоматически инициализируется (согласно спецификации языка C. 6.7.9 10): Если объект, имеющий статическую или длительность хранения потоков, не инициализируется , то: ... если он имеет арифметический тип, он инициализируется (положительным или беззнаковым) нолем; ...

Так static const a; отлично действует как const a если a глобальна и в тех случае a=0.

+0

Также возможно, что некоторые системы сборки могут определять средства, посредством которых вещи, которые будут постоянными после запуска программы, могут быть изменены между компиляцией и исполнением (например, с помощью утилиты, которая считывает карту ссылок и исправляет исполняемый файл). Стандарт C не предоставляет никаких средств, посредством которых такие вещи могут произойти, но нет никаких оснований для того, чтобы он запретил конструкцию, которая могла бы быть полезной с помощью таких средств. – supercat

Смежные вопросы