Функция C: это динамическое распределение? инициализация массива с изменяющейся длиной - PullRequest
2 голосов
/ 23 февраля 2010

Предположим, у меня есть функция C:

void myFunction(..., int nObs){
    int myVec[nObs] ;
    ...
}

myVec выделяется динамически? nObs не является постоянным всякий раз, когда вызывается myFunction. Я спрашиваю, потому что я в настоящее время программирую с этой привычкой, и у друга были ошибки в его программе, из-за чего он не распределял массивы динамически. Я хочу знать, является ли моя привычка программирования (инициализация, как в приведенном выше примере) безопасной привычкой.

Спасибо.

Ответы [ 3 ]

3 голосов
/ 23 февраля 2010

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

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

Он известен как " массив переменной длины ". Он динамический в том смысле, что его размер определяется во время выполнения и может изменяться от вызова к вызову, но он имеет класс хранения auto, как и любая другая локальная переменная. Я бы не стал использовать термин «динамическое распределение» для этого, поскольку это могло бы только ввести в заблуждение.

Термин «динамическое выделение» обычно используется для памяти и объектов, выделенных из кучи, время жизни которых определяется программистом (new / delete, malloc / free), а не областью действия объекта. Массивы переменной длины выделяются и уничтожаются автоматически по мере того, как они входят и выходят из области видимости, как и любая другая локальная переменная с auto классом хранения.

Массивы переменной длины не всегда поддерживаются компиляторами; в частности, VC ++ не поддерживает C99 (и, следовательно, массивы переменной длины), и нет никаких планов сделать это. C ++ в настоящее время не поддерживает их.

В связи с тем, что это «безопасная привычка», кроме проблемы переносимости, существует очевидный потенциал переполнения стека, если nObs будет достаточно большим значением. Вы можете до некоторой степени защититься от этого, например, сделав nObs меньшим целочисленным типом uint8_t или uint16_t, но это не очень гибкое решение, в котором сделаны смелые предположения относительно размера стека и объектов, являющихся выделены. assert(nObs < MAX_OBS) может быть целесообразным, но в этот момент стек может уже переполниться (хотя это может быть нормально, поскольку assert () в любом случае вызывает завершение).

[править] Использование массивов переменной длины, вероятно, хорошо, если размер не определен извне, как в вашем примере. [/ Править]

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

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

Это зависит от компилятора. Я знаю, что это нормально с gcc, но я не думаю, что спецификация C89 позволяет это. Я не уверен насчет новых спецификаций C, таких как C99. Лучшая ставка на мобильность - не использовать ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...