2015-08-25 2 views
9

У меня создалось впечатление, что объявления с переменным размером не были возможны на C89. Но при компиляции с clang -ansi я могу запустить следующий код:Использование sizeof() в объявлениях массивов в C89

double array[] = { 0.0, 1.0, 2.0, 3.0, 4.0 }; 
double other_array[sizeof(array)] = { 0.0 }; 

Что здесь происходит? Разве это не считается объявлением массива переменного размера?

+0

whaoppps, editied –

+1

Там нет массивы переменного размера в C89, поэтому он не может рассматриваться как объявление массива переменной величины. , –

ответ

5

Это происходит потому, что результат sizeof оператора константа, поэтому не может претендовать на VLA, так же, как следующее объявление:

int other_array[5]; 

не может быть переменной массива длины либо. Из C11 (N1570) §6.6/p6 Постоянные выражения (курсив мой идти вперед):

целочисленное постоянное выражение117) должен иметь целочисленный тип и должны иметь только операнды, которые являются целыми константами перечисление констант, символьные константы, sizeof выражения , результаты которых являются целыми константы, _Alignof выражения и плавающие константы, которые являются непосредственными операндами слепков.

Для полноты картины, оператор sizeof не всегда приводит к постоянному выражению, хотя это влияет только на пост-C89 стандартов (в C11 Власа были сделаны по желанию). Ссылаясь на п. 6.5.3.4/р2 sizeof В и _Alignof операторы:

Если тип операнда является тип переменной длины массива, то операнд; в противном случае операнд не оценивается, а результат является целочисленной константой.

3

Во-первых, давайте посмотрим критерии для массива (не является) VLA. C11 дока, глава §6.7.6.2,

[...] Если размером является постоянным выражением целого числа и типа элемента имеет известный постоянного размер, тип массива не является переменным длиной типа массива ; [...]

Далее в вашем случае, sizeof является оператором времени компиляции, поэтому он производит значение, которое считается постоянным выражением во время компиляции. Определение массива, размер которого определяется как выражение постоянной времени компиляции, не является VLA. Таким образом, в вашем коде

int other_array[sizeof(array)] 

не является VLA.

Что касается результата sizeof оператора, из C11, глава §6.5.3.4, (курсив мой )

Оператор sizeof дает размер (в байтах) своего операнда, который может быть выражением или имя в скобках типа. [...] в противном случае, операнд не оценивается и результат представляет собой целочисленную константу.

+2

В C11 'sizeof' не является« оператором компиляции »и иногда не создает постоянного выражения. (Хотя OP спрашивал о C89) –

8

В ANSI C89 ISO C90 А.К.А., оператор sizeof дает целая константа, которая подходит для измерений массива. Функциональных вызовов, например, нет.

Я хотел бы добавить еще одно замечание, так как я считаю, что код as-is имеет проблему, которая может быть упущена.

Если other_array объявлен как

double other_array[sizeof(array)]; 

он не будет ни иметь одинаковое число элементов, ни один и тот же размер, что (будет верно только для массива char) в качестве array[]. Если намерение состоит в том, чтобы объявить второй массив с таким же числом элементов (независимо от типа), используйте:

double other_array[sizeof(array)/sizeof(*array)]; 
+1

Почему downvote? – Jens

+3

Не мой нисходящий, но это не ответ на вопрос. Это должен быть комментарий. –

+0

@JensGustedt достаточно. Но я попытался на самом деле понять, что должен был сделать код, увидеть больше, чем технический вопрос, выяснить, почему кто-то хотел бы, чтобы другой массив был числом для каждого байта в двойном массиве. Это не выглядит правильным, и комментарии просто слишком ограничены, когда дело доходит до форматирования. Возможно, я должен повторить технический ответ в третий раз, чтобы соответствовать ожиданию ответа. – Jens

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