В C, почему переменная const не может использоваться как инициализатор размера массива?

В следующем коде const int не может использоваться как размер массива:

const int sz = 0;
typedef struct
{
   char s[sz];
} st;

int main()
{
   st obj;
   strcpy(obj.s, "hello world");
   printf("%s", obj.s);
   return 0;
}

Ответ 1

В C переменная const -qualified не является константным выражением 1. Постоянное выражение - это то, что может быть оценено во время компиляции - числовой литерал, такой как 10 или 3.14159, строковый литерал, например "Hello", выражение sizeof или какое-то выражение, составленное из того же типа 10 + sizeof "Hello".

Для объявлений массива в области видимости файла (вне тела любой функции) или как члены типов struct или union размер массива должен быть константным выражением.

Для массивов auto (массивы, объявленные в теле функции, которые не являются static), вы можете использовать переменную или выражение, значение которого неизвестно до выполнения, но только на C99 или более поздней версии.


  • С++ отличается в этом отношении - на этом языке переменная const -qualified считается как постоянное выражение.

Ответ 2

Это потому, что в C const на самом деле означает только чтение. Цитирование C FAQ 1.18 и 1.19:

Определитель const действительно означает `` только для чтения ''; объект, который имеет такую ​​квалификацию, является объектом времени выполнения, который не может (обычно) назначаться. Таким образом, значение const-квалифицированного объекта не является постоянным выражением в полном смысле этого слова и не может использоваться для размеров массива, ярлыков меток и т.п. (C отличается от С++ в этом отношении.) Когда вам нужна истинная константа времени компиляции, используйте препроцессор #define (или, возможно, перечисление).

Ссылки: ISO Sec. 6,4 H & S Sec. 7.11.2.7.11.3 стр. 226-7

Есть два способа борьбы с ним:

  • Используйте #define вместо const
  • Используйте enum { sz = 12 };

Ответ 3

Очень просто, потому что компилятор должен знать размерность массива во время компиляции, и поскольку вы можете инициализировать const variable во время выполнения, вы не сможете этого сделать. Поэтому размер статически ограниченных массивов должен быть константным выражением, а const variable - не он. Для постоянного выражения вы должны использовать: #define или enum. Это явно для вас (в области файлов), и если вы используете минимальный стандарт c99