2013-09-17 2 views
4

C99 позволяет определять массивы с непостоянным размером, то есть размер, используемый для определения массива, может меняться во время выполнения. Фрагмент кода, чтобы объяснить, что это будет,массивы переменной длины в C и их инициализация

void dummy_function1(unsigned int length) { 

char arrA[length]; //Allowed 
. 
. 
} 

Однако, это не позволяет инициализировать его на месте, т.е.

void dummy_function2(unsigned int length) { 

char arrA[length]={0}; //Not Allowed, compiler throws an error 
char arrB[10]={0};  //Allowed 
. 
} 

Я не понимаю, почему это различие в поведении для массива, который является переменной длина и постоянная длина. В обоих случаях массив будет иметь память при вызове функции.

+0

'length' - это не постоянная времени компиляции. Он будет вводиться пользователем во время выполнения. При компиляции значение времени 'length' не известно компилятору. – haccks

+1

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

ответ

4

Это связано с тем, что компилятор не знает, сколько нулей «заполнить» оставшиеся элементы.

Заявление

char arrA[3] = { 0 }; 

легко могут быть переведены на

char arrA[3] = { 0, 0, 0 }; 

во время компиляции, в то время как объявление переменной длины не может.

Поскольку C не имеет системы исполнения, компилятор должен будет добавить код для динамического ввода с нулями в зависимости от заданной длины. Стандарт C стремится быть минимальным с максимальной мощностью для программиста, и поэтому такие вещи избегают. Начиная с C11, массивы переменной длины были удалены из стандарта и помечены как необязательная функция.

+1

Кроме того, если length = 0, это будет ошибка. –

+1

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

+0

Я добавил некоторую информацию в свой ответ :) –

4

Похоже, это не допускается стандартом, если мы посмотрим на проекте C99 стандартной секция 6.7.8инициализации пункта говорит (курсив мой):

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

В связи с тем, что, скорее всего, потому что поддержка инициализации массива переменной длины потребует неопределенного объема работы во время выполнения.

+1

Возникает вопрос, почему стандарт C 1999 не поддерживает инициализацию массивов переменной длины. Этот ответ не отвечает на этот вопрос. –

+0

@EricPostpischil Хммм, я мог бы поклясться, что это изначально не читалось, но это очень возможно, я просто интерпретировал по-другому в то время ... Я обновлю –

2

Гипотеза: C является языком среднего уровня, и комитет по стандартизации не хотел включать операции на базовом языке (считая библиотеку как отдельную), которые выполняют объем работы, не определенный во время компиляции.

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

Даже для выделения пространства для массива переменной длины требуется только время работы с компиляцией: вычислить размер и вычесть из указателя стека. Напротив, для инициализации всего этого пространства требуется определенная работа во время выполнения. Это не характерно для языка C.

В библиотечных процедурах может потребоваться объем работы, определенный во время выполнения, например memset.

+0

Имеет смысл, вроде, хотя VLA все еще использует неизвестное (во время компиляции) количество другого, часто ограниченного ресурса (стека). Допустив это, бесполезно судить о неизвестном количестве циклов CPU и принуждении программиста к явному вызову memset (который, вероятно, генерирует идентичный код после оптимизации). – hyde

+0

+1 для того, чтобы поймать деталь, которую пропустили остальные. –

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