Константная корректность в C vs С++
Я понимаю, что такое const correctness, и мой вопрос не в том, что такое const correctness. Поэтому я не ожидаю объяснений или ссылок на С++ - FAQ для этого.
Мои вопросы:
- Каковы семантические различия между
const
в C и const
в С++? и
- В чем причина разницы?
Цитаты из соответствующих стандартов, которые делают различия четкими, было бы неплохо иметь.
Я регулярно переключаюсь между C и С++, и я хотел бы знать важные моменты, о которых следует помнить при этом.
Кажется, я не помню причину этих (особая благодарность, если вы можете дать аргументацию), но, с моей точки зрения, я помню:
- константные переменные в С++ имеют внутреннюю привязку по умолчанию, а в C - внешняя связь по умолчанию;
- const объекты могут использоваться как значения времени компиляции в С++, но не могут использоваться как значения времени компиляции в C;
- Указатели на строковые литералы должны быть
char const*
в С++, но в C это может быть char*
.
Что мне не хватает?
Ответы
Ответ 1
В дополнение к различиям, которые вы цитируете, и различиям в библиотеке, которые
Стив Джессоп упоминает,
char* p1;
char const* const* p2 = &p1;
является законным в С++, но не в C. Исторически это происходит потому, что C
изначально разрешено:
char* p1;
char const** p2 = &p1;
Незадолго до принятия стандарта кто-то понял, что это
пробивает дыру в const безопасности (поскольку *p2
теперь можно назначить
char const*
, что приводит к тому, что p1
присваивается a char const*
); с
нет реального времени для углубленного анализа проблемы, комитет С запретил любые
дополнительный const
, отличный от верхнего уровня const. (I.e. &p1
может быть
присваивается char **
или char **const
, но не к char const**
ни a char const* const*
.) Комитет С++ сделал дальнейшее
анализ, понял, что проблема была только тогда, когда a const
уровень сопровождался уровнем не const
и выработал необходимый
формулировка. (См. §4.4/4 в стандарте.)
Ответ 2
В объявлениях C const
не создаются постоянные выражения, то есть в C вы не можете использовать объект const int
в ярлыке case, в качестве ширины битового поля или размера массива в объявлении массива без VLA (все это возможно в С++). Кроме того, объекты const имеют внешнюю связь по умолчанию в C (внутренняя связь в С++).
Правила Const-correctness языка С++ поддерживают следующее стандартное преобразование
int **pp = 0;
const int *const *cpp = pp; // OK in C++
int ***ppp = 0;
int *const *const *cppp = ppp; // OK in C++
Они не будут работать в c.
Ответ 3
Причина некоторых из этих различий заключается в том, чтобы позволить нам избавиться от макросов препроцессора, что было одним из ранних целей дизайна Bjarne.
В C мы могли бы иметь
#define MAX_FOOS 10
int foos[MAX_FOOS];
В С++ мы предпочли бы писать
const int max_foos = 10;
int foos[max_foos];
Для этого работать max_foos
необходимо использовать в постоянном выражении. Он также должен иметь внутреннюю связь, поэтому определение может отображаться в заголовке, не вызывая множественных ошибок определения, и что более важно, чтобы упростить компилятору не выделять какое-либо хранилище для max_foos
.
Когда комитет C принял const из С++, они не приняли антипатию к макросам, поэтому им не нужны эти семантики.