Как динамическое распределение памяти лучше, чем массив? - PullRequest
1 голос
/ 06 июля 2011
int numbers*;
numbers = malloc ( sizeof(int) * 10 );

Я хочу знать, каково это динамическое распределение памяти, если я могу сохранить только 10 int элементов в блоке памяти? Я мог бы просто использовать массив и динамически хранить элементы, используя индекс. Почему вышеуказанный подход лучше?

Я новичок в C, и это мой второй день, и я могу показаться глупым, поэтому, пожалуйста, потерпите меня.

Ответы [ 7 ]

4 голосов
/ 06 июля 2011

В этом случае вы можете заменить 10 на переменную, которая назначается во время выполнения. Таким образом, вы можете решить, сколько памяти вам нужно. Но с массивами вы должны указать целочисленную константу во время объявления. Поэтому вы не можете решить, нужно ли пользователю фактически столько мест, сколько было объявлено, либо, что еще хуже, этого может быть недостаточно.

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

Это помогает обеспечить оптимальное использование памяти.

4 голосов
/ 06 июля 2011

Основная причина, по которой malloc() полезна, это , а не , поскольку размер массива можно определить во время выполнения - современные версии C допускают это и с обычными массивами.Есть две причины:

  • Объекты, выделенные с помощью malloc(), имеют гибкое время жизни;

То есть вы получаете во время выполнения контроль над тем, когда создавать объект и когдауничтожьте это.Массив, выделенный с помощью malloc(), существует с момента вызова malloc() до соответствующего вызова free();напротив, объявленные массивы либо существуют до тех пор, пока не будет объявлена ​​функция, в которой они объявлены при выходе, либо пока программа не завершит работу.

  • malloc() сообщает об ошибке, что позволяет программе корректно обработать ее.

При неудачном выделении запрошенной памяти malloc() может вернуть NULL, что позволяет вашей программе обнаруживать и обрабатывать условие.Для объявленных массивов такого механизма не существует - при неудачном выделении достаточного пространства либо происходит сбой программы во время выполнения, либо она не загружается вообще.

3 голосов
/ 06 июля 2011

Есть разница с тем, где выделена память. Используя синтаксис массива, память распределяется в стеке (при условии, что вы находитесь в функции), а массивы / байты, выделенные malloc, выделяются в куче.

/* Allocates 4*1000 bytes on the stack (which might be a bit much depending on your system) */
int a[1000];

/* Allocates 4*1000 bytes on the heap */
int *b = malloc(1000 * sizeof(int))

Распределение стека происходит быстро и часто предпочтительнее, когда:

  • Требуется «маленький» объем памяти
  • Указатель на массив не должен возвращаться функцией

Распределение кучи медленнее, но имеет преимущества:

  • Доступная куча памяти (обычно) >> чем доступная память стека
  • Вы можете свободно передавать указатель на выделенные байты, например, возвращая его из функции - просто не забудьте освободить его в какой-то момент.

Третий вариант - использовать статически инициализированные массивы, если у вас есть какая-то общая задача, для которой всегда требуется массив некоторого максимального размера. Поскольку вы можете сэкономить память, статически потребляемую массивом, вы избежите попадания в выделение памяти для кучи, получите гибкость для перемещения указателя и избегаете необходимости отслеживать владение указателем, чтобы гарантировать освобождение памяти.

Редактировать: Если вы используете C99 (по умолчанию с компилятором gnu c, я думаю?), Вы можете создавать массивы стеков переменной длины, например

int a = 4;
int b[a*a];
2 голосов
/ 06 июля 2011

В приведенном вами примере

int *numbers;
numbers = malloc ( sizeof(int) * 10 );

явных преимуществ нет. Однако представьте, что 10 - это значение, которое изменяется во время выполнения (например, пользовательский ввод), и вам нужно вернуть этот массив из функции. Э.Г.

int *aFunction(size_t howMany, ...)
{
    int *r = malloc(sizeof(int)*howMany);
    // do something, fill the array...
    return r;
}

Маллок занимает место из кучи, а что-то вроде

int *aFunction(size_t howMany, ...)
{
    int r[howMany];
    // do something, fill the array...
    // you can't return r unless you make it static, but this is in general
    // not good
    return somethingElse;
}

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

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

1 голос
/ 06 июля 2011

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

например. int numbers[10];

Это будет распределять память статически, и это будет непрерывная память.

Если вы не в курсе количества чисел, используйте переменную типа count.

int count;
int *numbers;
scanf("%d", count);
numbers = malloc ( sizeof(int) * count );

Это невозможно в случае массивов.

1 голос
/ 06 июля 2011

Размер массива определяется во время компиляции, тогда как динамическое выделение выполняется во время выполнения.

Таким образом, в вашем случае вы можете использовать указатель в качестве массива: numbers[5] допустимо.

Если вы не знаете размер вашего массива при написании программы, использование времени выполнения не является выбором.В противном случае вы можете использовать массив, это может быть проще (меньше риска, например, забыть освободить память)

Пример:

  • для хранения трехмерной позиции, вы можете использовать массив, поскольку он всегда имеет 3 координаты
  • , чтобы создать сито для вычисления простых чисел, вы можете использовать параметр, чтобы задать максимальное значение и, таким образом, использовать динамическое распределение для создания области памяти.
0 голосов
/ 06 июля 2011

Динамический не относится к доступу.Динамический размер malloc.Если вы просто используете постоянное число, например, как 10 в вашем примере, это не что иное, как массив.Преимущество заключается в том, что вы заранее не знаете, насколько он велик, например, потому что пользователь может ввести размер во время выполнения.Затем вы можете выделить переменную, например, malloc(sizeof(int) * userEnteredNumber).Это невозможно с массивом, так как вы должны знать там во время компиляции (максимальный) размер.

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