Неплохая ли практика объявлять среднюю функцию массива?

в попытке только спросить, что я действительно ищу здесь … Меня действительно беспокоит только то, что считается плохой практикой или не объявлять массив, как показано ниже, где размер может меняться. Если это … Я бы вообще malloc ().

void MyFunction() { int size; //do a bunch of stuff size = 10; //but could have been something else int array[size]; //do more stuff... } 

Как правило, да, это плохая практика, хотя новые стандарты позволяют использовать этот синтаксис. По-моему, вы должны выделить (в кучу) память, которую хотите использовать, и отпустить ее, как только вы закончите с ней. Поскольку нет переносного способа проверки того, достаточно ли стека для хранения этого массива, вы должны использовать некоторые методы, которые действительно можно проверить – например, malloc / calloc & free. Во встроенном мире размер стека может быть проблемой.

Если вас беспокоит fragmentация, вы можете создать свой собственный распределитель памяти, но это совершенно другая история.

Это зависит от. Первое, очевидно, не то, что я назвал бы «правильным», а второе – лишь в весьма ограниченных обстоятельствах.

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

Во втором случае вы ограничиваете код C99 или gcc-расширением. Пока вы это осознаёте, и это работает для ваших целей, все в порядке, но вряд ли я бы назвал идеал переносимости.

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

По вашему вопросу, я думаю, каждый имеет свои преимущества и недостатки.

Динамическое распределение:
Медленно, но вы можете обнаружить, когда память не будет передана вашему программисту, проверив указатель.

Распределение стека:
Только в C99, и это невероятно быстро, но в случае stackoverflow вам не повезло.

Итак, когда вам нужен небольшой массив, зарезервируйте его в стеке. В противном случае разумно используйте динамическую память.

Аргумент против VLA запускается из-за абсолютной неэффективности переполнения стека, к тому времени, когда вы сделали достаточное количество мышления / проверки, чтобы сделать их безопасными, вы сделали достаточно мышления / проверки для использования массива фиксированного размера:

1) Чтобы безопасно использовать VLA, вы должны знать, что имеется достаточно стека.

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

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

4) Если вы столкнулись с одним из оставшихся случаев, в ситуации, когда производительность malloc неприемлема, сообщите мне …

Из POV исходного кода может быть более удобно использовать VLA. Например, вы можете использовать sizeof (в области определения) вместо того, чтобы поддерживать размер в переменной, и что бизнес с разделением массива на куски может потребовать передачи дополнительного параметра. Так что иногда есть небольшой выигрыш в удобстве.

Также проще пропустить, что вы используете огромное количество стека, что дает неопределенное поведение, если вместо довольно страшного типа int buf[1920*1024] или int buf[MAX_IMG_SIZE] вас есть int buf[img->size] . Это прекрасно работает до тех пор, пока вы на самом деле не справитесь с большим изображением. Это в целом проблема правильного тестирования, но если вы пропустите некоторые возможные сложные входы, то это не будет первый или последний набор тестов для этого. Я нахожу, что массив фиксированного размера напоминает мне, чтобы либо установить фиксированные проверки ввода, либо заменить его динамическим распределением, и перестать беспокоиться о том, подходит ли он в стеке или нет. Нет допустимого варианта, чтобы поместить его в стек и не беспокоиться, подходит ли он …

две точки с точки зрения UNIX / C –

malloc работает только медленно, когда вы вынуждаете его вызывать brk (). Значение для разумных массивов – это то же самое, что и распределение пространства стека для переменной. Кстати, когда вы используете метод # 2 (через alloca и в коде libc, который я видел) также вызывает brk () для огромных объектов. Так что это мытье. Примечание: с # 2 и # 1 вам все равно придется вызывать прямо или косвенно вызов типа memset для нулевого байта в массиве. Это просто примечание к реальной проблеме (ИМО):

Реальная проблема – утечки памяти. alloca очищает после себя, когда функция retruns так что # 2 с меньшей вероятностью вызовет проблему. С помощью malloc / calloc вы должны вызвать free () или запустить утечку.