Ссылаясь на значение const во время компиляции - когда действительно доступно определение const? - PullRequest
1 голос
/ 14 февраля 2010

Я пытался

const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // g++ cries "error: array bound is not an integer constant"

int main()
{
   const int j[] = { 0, 1, 2, 3 };
   float g[j[3]];                   // compiler is happy :)

   return 0;
}

В чем разница между двумя агрегатами? Почему обращение к элементу агрегата const внутри main () допустимо, если оно недопустимо в глобальной области видимости?

Ответы [ 3 ]

10 голосов
/ 14 февраля 2010

В C ++ размеры в объявлении массива должны быть выражениями Integral Constant (ICE). По определению, ICE в C ++ не может включать значение, взятое из массива, независимо от того, является ли он массивом const или нет. Таким образом, в обоих случаях i[3] и j[3] не являются ICE и не могут использоваться в качестве размеров в объявлениях массива. По этой причине оба объявления - f и g - недопустимы в C ++.

Однако, поскольку вы используете GCC, во втором случае вступает в действие нестандартное расширение компилятора. Когда вы объявляете автоматический массив, GCC позволяет вам указать непостоянный размер (то есть размер времени выполнения) для массива (это в основном VLA C99, перенесенные в C ++). Вот почему он «счастлив», хотя код на C ++ недопустим. Скомпилируйте в режиме -ansi -pedantic-error, и вы должны получить диагностическое сообщение (ошибку) для каждого объявления.

1 голос
/ 14 февраля 2010

Компилятор может использовать эти константы в качестве констант времени компиляции, которые он может хранить в своей таблице символов. Но фактически ни один компилятор не является настолько сложным, чтобы хранить агрегат в его таблице символов, поэтому значение не может использоваться во время компиляции. Кроме того, нестандартные расширения gcc позволяют использовать автоматические массивы переменной длины. Вот почему не только это:

const int j[] = { 0, 1, 2, 3 };
   float g[j[3]]; 

но также это разрешено компилятором:

int j[] = { 0, 1, 2, 3 };
   float g[j[3]];
0 голосов
/ 14 февраля 2010

GCC 3.4.5 говорит, что «тип переменной размера объявлен вне какой-либо функции», а 4.4.0 говорит, что «граница массива не является целочисленной константой» для f[i[3]], что приводит меня к мысли, что ни i[3], ни j[3] постоянно, хотя я не могу сказать вам, почему. Если бы мне пришлось сделать дикое предположение, я бы сказал, что, возможно, это как-то связано с тем, что адреса i и j неизвестны до времени ссылки, но я действительно не уверен.

Редактировать: меня избили. Оставив позади мой низший ответ для потомков.

...