Почему мы должны использовать mallo c () или любую другую Dynami c память для массивов в C? - PullRequest
0 голосов
/ 21 января 2020

Рассмотрим эти коды в C:

int n;  
scanf("\n%d ",&n);  
int arr[n];

и это.

int n;
scanf("\n%d ",&n);
int *p = (int *)malloc(n*sizeof(int));  

Зачем нам в первую очередь динамическое c выделение памяти для этого?
и является ли первый код не Dynami c Выделение памяти, поскольку массив создается во время выполнения?

Когда мне следует использовать mallo c ()?

Ответы [ 4 ]

2 голосов
/ 21 января 2020

int arr[n]; выделяет память в стеке . автоматически распределяется и затем освобождается в конце блока . Указатель на стековую память не может быть безопасно возвращен из функции.

Учтите это.

#include <stdio.h>

char *make_array() {
    int n;  
    scanf("%d",&n);

    // Memory for `arr` is allocated on the stack.
    char arr[n];

    // And then deallocated when the function exits.
    // A good compiler and editor will warn you if you try
    // to return it.
    return arr;
}

int main() {
    // This pointer is to memory which has already been freed. Other things
    // will overwrite it.
    char *arr = make_array();

    arr[0] = 'c';
    arr[1] = '\0';

    // This could be the letter c, but it's probably gibberish.
    puts(arr);
}

Если вам нужна память, чтобы жить дольше, чем текущая функция, вам нужно выделить ее в кучу с malloc и управляй им сам.

1 голос
/ 21 января 2020

Просто чтобы убедиться, что вы понимаете:

Когда «функции вызывают функции», их локальные переменные хранятся в области памяти, известной как «стек», названной так, потому что она работает как pu * 1013. * вниз LIFO стека. Когда функция введена, стек увеличивается. Когда функция возвращается, она сжимается. И если функция рекурсивно вызывает , , то нет путаницы, потому что каждый экземпляр имеет свою собственную область в стеке.

malloc() выделяет память «по запросу» из другой области, называемой « куча, "так назван, потому что он не имеет конкретной встроенной организации. На эти области памяти ссылаются косвенно, , используя «указатели», которые являются переменными, значение которых понимается как адрес памяти.

Язык «C» удобно использовать «обозначение массива» при использовании указателей, так же, как это происходит с локальными переменными, размещенными в стеке.

0 голосов
/ 21 января 2020
int n;  
scanf("\n%d ",&n);  
int arr[n];

, где n - это значение c динамического исполнения (как в данном случае), которое не поддерживалось в более старых версиях C, для которых требовалось, чтобы n была целочисленной константой expression.

Современные версии C сняли это ограничение, разрешив использовать динамически изменяемые массивы (массивы переменной длины или VLA), но в отличие от старых массивов фиксированного размера, VLA имеют ограничения.

Им не разрешено перепрыгивать (с break / continue / goto), они могут быть не асин c -signal-safe, они взломают sh вашу программу, если получат слишком большой, и они часто генерируют больший код, чем обычные старые локальные массивы.

Кроме того, поскольку они локальные, вы не можете вернуть указатель на них вызывающей стороне.

ограничение размера является одним из их самых больших ограничений. VLA вырезаны из стека вызовов, который обычно составляет всего пару килограмм / мегабайт, и вы получите обычно невыявленный cra sh, если вы превысите этот предел.

malloc 'd память не имеет такого ограничения, malloc сбои четко передаются через возвращенный NULL, и, поскольку malloc память является глобальной для процесса, вы можете передать указатель на нее обратно своему вызывающему.

`

0 голосов
/ 21 января 2020
int n;  
scanf("\n%d ",&n);  
int arr[n];

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

...