Intereting Posts

Что означает «int const a »?

Рассмотрим следующее объявление массива:

int const a[5]; 

С семантической точки зрения языка, она в точности эквивалентна const int a[5] ? Предполагая, что это так, обе декларации будут по существу читать как « a – массив из 5 константных ints ».

Альтернативным способом чтения первого объявления будет « a – это постоянный массив из 5 ints ».

Очевидно, что оба утверждения логически предполагают, что весь массив является постоянным; если массив состоит из 5 постоянных ints, тогда весь массив является постоянным. Альтернативно, если весь массив является постоянным, то все его значения также являются постоянными.

Я знаю, что понятие «постоянного массива» немного бессмысленно, так как массивы не изменяются lvalues ​​(то есть они не могут появляться с левой стороны задания). Однако существуют ли какие-либо обстоятельства, при которых эти два заявления могут привести к другому поведению?

( Cdecl.org отклоняет первое объявление как синтаксическую ошибку, в то время как большинство современных компиляторов принимают его.)

РЕДАКТИРОВАТЬ:

Связанный дубликат спрашивает, имеет ли порядок const для обычных переменных. С массивами это немного более запутанно, поэтому я не считаю это дубликат.

это точно эквивалентно const int a[5]

Да, это.

Альтернативным способом чтения первого объявления будет «a – это постоянный массив из 5 ints».

На самом деле, нет. Ваше объявление, как написано, применяет элементы const к массиву. Чтобы применить const к самому массиву (в отличие от применения его к элементам массива), вам нужно будет сделать что-то вроде

 int (const a)[5]; 

но такое заявление синтаксически недействительно в C.

Косвенная попытка применить const к самому массиву может быть выполнена через промежуточный typedef

 typedef int A[5]; const A a; 

но в этом случае, по языковым правилам, const «проваливается» к элементам массива, и все это просто эквивалентно

 const int a[5]; 

Заметим еще раз, что const A a; выше не сразу эквивалентно const int a[5]; , Это фактически эквивалентно вышеупомянутому int (const a)[5]; (!). (Это законный способ скрывать int (const a)[5]; , защита прошлого компилятора.) Но это int (const a)[5]; очень короткий – он сразу превращается в const int a[5]; компилятором.

если массив состоит из 5 постоянных ints, тогда весь массив является постоянным. Альтернативно, если весь массив является постоянным, то все его значения также являются постоянными.

Ну, это не совсем так. Язык C различает объект массива и его элементы. Концептуально это разные сущности. Например, как вы отметили сами, спецификация языка говорит о том, что массивы не изменяются lvalues . Это, конечно, не препятствует модификации элементов массива.

Это концептуальное различие между массивом как целого и отдельными элементами массива в сочетании с «провальным» поведением для const является именно тем, что приводит к следующей неприятной ситуации

 typedef int A[5]; A a; const A *p = &a; // ERROR!!! 

т.е. он нарушает «нормальное» правило const-correctness, которое позволяет нам инициализировать указатели const T * с значениями T * . (C ++ намеренно обновлял правила констант-правильности, чтобы заставить вышеуказанный код вести себя «как ожидалось», но C настаивает на его отказе).

Я поставил это вместе:

 #include  int main() { int const a[5]; const int b[5]; int c[5]; a[0] = 1; b[0] = 2; c = a; c = b; } 

И gcc (4.1.2) выплюнул:

 gcc -o /tmp/x2 /tmp/x2.c /tmp/x2.c: In function 'main': /tmp/x2.c:9: error: assignment of read-only location /tmp/x2.c:10: error: assignment of read-only location /tmp/x2.c:11: error: incompatible types in assignment /tmp/x2.c:12: error: incompatible types in assignment 

Поэтому, по крайней мере, на основании этого нет никакого различия.