Распределение памяти mallo c Dynami c? - PullRequest
5 голосов
/ 03 августа 2020

Преподаватель сказал мне, что p = (int*)malloc(5 * sizeof(int)) - это НЕ динамическое c выделение памяти и что p=(int*)malloc(n * sizeof(int)) - динамическое c выделение памяти.

Инструктор говорил о структурах данных basi c и обучал массивам. Он рассказал нам о традиционном способе создания массивов с использованием синтаксиса int arr[100], но затем представил нам mallo c.

По его словам, поскольку размер памяти не меняется, это не динамика c Я думаю.

Из того, что я мог узнать из inte rnet, malloc назначает память во время выполнения, а когда память назначается во время выполнения, его динамическое c распределение памяти. Итак, я думаю, что оба оператора malloc - это динамические c распределения памяти. Что-то не так с моими рассуждениями?

Ответы [ 4 ]

7 голосов
/ 03 августа 2020

Обычно мы называем вызовы malloc динамическим c выделением, независимо от того, используете ли вы переменную или константу. Даже справочная страница для malloc называет это так:

mallo c, бесплатно, callo c, reallo c - выделить и освободить динамику c память

Итак, для ваших инструкторов заявите:

Преподаватель говорил о базовых c структурах данных и обучал массивам. Он рассказал нам традиционный способ создания массивов с использованием синтаксиса int arr [100], но затем он представил нам mallo c.

По его словам, поскольку размер памяти не меняется, это не динамическое c Я полагаю.

Ну, в некотором смысле он прав, если вы строго посмотрите на то, что означает «Dynami c» в более общем смысле. Прямо сейчас у нас есть соглашение, которое вызывает выделение всех malloc динамических c. Это соглашение могло быть таким, как утверждает ваш учитель, без каких-либо проблем. Но это не так.

Более того, согласно рассуждениям ваших учителей, использование VLA: s (массив переменной длины) или alloca с переменной будет считаться динамическим c распределением, но это не так. VLA может быть объявлен следующим образом: int arr[n] или alloca эквивалент: int *arr = alloca(n*sizeof(*arr)).

Так что даже если вы могли возразить, что ваш учитель прав, это только вызовет путаницу, поскольку это противоречит соглашению.

Кроме того, самая динамичная c вещь в использовании malloc - это то, что размер выделения можно изменить позже. Вы не можете сделать это с массивами, даже с VLA: s. И вы не можете сделать это с памятью, которую вы выделили с помощью alloca.

Но в качестве примечания, я сомневаюсь в компетентности ваших учителей, если они учат вас писать

p = (int*)malloc(n * sizeof(int)) 

вместо

p = malloc(n * sizeof(*p))
  1. Приведение не требуется, просто добавляется беспорядок
  2. Использование sizeof(*p) вместо sizeof(int) безопаснее

Связано: Привести ли результат mallo c?

5 голосов
/ 03 августа 2020

Стандарт C не определяет термин «динамическое c выделение памяти». Таким образом, мы не можем взять стандарт C и выяснить, что такое динамическое c распределение памяти.

Стандарт C говорит о «функциях управления памятью» (например, выровненный_алло c, вызов c, mallo c, reallo c и бесплатно). Когда используются эти функции, это обычно называется динамическим c выделением памяти, но, повторюсь, это не термин из стандарта.

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

Обе строки кода в вопросе составляют p точку объекту, у которого есть «выделенная продолжительность хранения».

Я предполагаю, что вы неправильно поняли своего учителя, то есть неправильно поняли, что имелось в виду под «динамическим c». Возможно, ваш учитель говорил о размере выделенного объекта, например:

p = (int*)malloc(5 * sizeof(int));   // Here the size is static - always 5 ints

p = (int*)malloc(n * sizeof(int));   // Here the size is dynamic (aka depends on n)

Примечание: приведение, например, (int*), не требуется в C.

4 голосов
/ 03 августа 2020

Либо вы неправильно понимаете то, что пытался сказать ваш инструктор, либо ваш инструктор очень и очень плохо высказывал свою точку зрения (что, честно говоря, не редкость, особенно когда речь идет об обучении C). *

Оба вызова malloc в вашем вопросе - это динамическое c выделение памяти. Единственное отличие состоит в том, что первая форма выделяет известный фиксированный объем памяти при каждом выполнении, тогда как вторая может выделять другой объем при каждом выполнении. Это не делает первую форму не динамической c выделением.

Память в обоих случаях может быть изменен размер с помощью вызова realloc.

И в качестве стилистического c примечания, вам не нужно преобразовывать результат malloc в C 1 . Гораздо менее утомительно писать

p = malloc( 5 * sizeof *p ); 

или

p = malloc( n * sizeof *p );

sizeof *p то же самое, что sizeof (int) (при условии, что p был объявлен как int *p). Это упрощает обслуживание, поскольку вам не нужно повторять информацию о типе несколько раз.


Это не так в C ++, но если вы пишете C ++, вам не следует » в любом случае использовать malloc.
3 голосов
/ 03 августа 2020

Преподаватель сказал мне, что p = (int*)malloc(5 * sizeof(int)); - это НЕ динамическое c выделение памяти и что p = (int*)malloc(n * sizeof(int)); - динамическое c выделение памяти

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

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

Оба назначения блока памяти могут быть изменены позже, в среде выполнения они, следовательно, являются динамическими c, тогда как в объявлении массива, т.е. int arr[100] назначенная память фиксирована, ее нельзя изменить, поэтому она не является динамической. c.

Однако есть различия в использовании константы или переменной, очевидная из которых - возможность использования значение переменной, которая будет определять размер блока памяти во время выполнения. И, как очень точно указал @ cmaster-reinstatemonica , использование константы в качестве определителя размера для блока памяти позволяет при определенных обстоятельствах оптимизировать компилятор до malloc, что имеет смысл, учитывая тот факт, что это может быть дорогая функция.

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

Некоторые хорошие соображения относительно правильного использования malloc сделаны @ JohnBode , я настоятельно рекомендую вам следовать им , на самом деле, весь ответ очень хорош, и на него следует обратить внимание вашего инструктора, если вы чувствуете себя комфортно с ним, вы сможете прояснить вопрос.

...