Язык C: Почему malloc () возвращает указатель, а не значение? - PullRequest
2 голосов
/ 13 октября 2011

Из моего понимания C кажется, что вы должны использовать malloc (размер) всякий раз, когда пытаетесь инициализировать, например, массив, размер которого вы не знаете до времени выполнения.

Но ямне было интересно, почему функция malloc () возвращает указатель на местоположение переменной и зачем вам это вообще нужно.

По сути, почему C не прячет все это от вас,так что всякий раз, когда вы делаете что-то вроде этого:

    // 'n' gets stdin'ed from the user
    ...
    int someArray[n];

    for(int i = 0; i < n; i++)
        someArray[i] = 5;

, вы можете сделать это без необходимости вызова malloc () или какой-либо другой функции?Другие языки делают это так (полностью скрывая свойства / местоположение памяти)?Я чувствую, что, как новичок, весь этот процесс работы с расположениями в памяти переменных, которые вы используете, просто сбивает с толку программистов (и поскольку другие языки не используют его, C, кажется, делает простой процесс инициализации, такой как этот, чрезмерно сложный) ...

По сути, я пытаюсь спросить, почему malloc () даже необходим, потому что язык не заботится обо всем этом для вас внутренне, без необходимости заботиться о программисте илиувидеть память.Спасибо

* edit: Хорошо, возможно, есть некоторые версии C, о которых я не знаю, которые позволяют вам отказаться от использования malloc (), но давайте попробуем проигнорировать это сейчас ...

Ответы [ 9 ]

7 голосов
/ 13 октября 2011

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

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

4 голосов
/ 13 октября 2011

По сути, я пытаюсь спросить, почему malloc () даже необходим, потому что язык не заботится обо всем этом для вас внутренне без необходимости заботиться о программисте илисм. память.

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

C близок к 40 годам, и это не такой высокий уровень, как некоторыесовременные языки.Некоторые языки, такие как Java, пытаются предотвратить ошибки и упростить программирование, скрывая указатели и явное управление памятью от программиста.С не так.Зачем?Потому что это просто не так.

4 голосов
/ 13 октября 2011

На самом деле C99 позволяет это (так что вы не единственный, кто об этом думает).Функция называется VLA (VAriable Length Array).

Допустимо прочитать int, а затем иметь массив такого размера:

int n;
fscanf("%d", &n);
int array[n];

Конечно, существуют ограничения, так как malloc использует кучу, а VLA s использует стек (поэтому VLA не могут быть такими большими, как malloc ed-объекты).

* edit: Ok, возможно, есть некоторыеверсии C, о которых я не знаю, которые позволяют вам отказаться от использования malloc (), но давайте попробуем пока игнорировать это ...

Так что мы можем сосредоточиться на пламени?

3 голосов
/ 13 октября 2011
По сути, я пытаюсь спросить, почему malloc () даже необходим, потому что язык не заботится обо всем этом для вас внутренне, без необходимости заботиться о программисте или видеть память. Спасибо

Одним из отличительных признаков C является его простота (компиляторы C относительно просты в реализации); Один из способов упростить язык - заставить программиста самостоятельно управлять памятью. Очевидно, что другие языки do управляют объектами в куче для вас - Java и C # являются современными примерами, но концепция вовсе не нова; Реализации Lisp делают это десятилетиями. Но это удобство обходится как сложностью компилятора, так и производительностью.

Подход Java / C # помогает устранить целые классы ошибок управления памятью, свойственных C (утечки памяти, недопустимые разыменования указателей и т. Д.). Кроме того, C обеспечивает уровень контроля над управлением памятью, который позволяет программисту достигать высоких уровней производительности, которые было бы трудно (не невозможно) сопоставить на других языках.

2 голосов
/ 14 октября 2011

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

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

malloc() дает вам лот больше гибкости.

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

Вы также можете использовать malloc() вместе с realloc() для создания буфера (скажем, массив unsigned char), размер которого можно изменить после его создания.

Да, есть языки, в которых нет указателей и которые управляют памятью для вас.

Многие из них реализованы в C.

1 голос
/ 13 октября 2011

Краткий ответ на ваш вопрос - подумать над этим вопросом: что, если вам также необходимо точно контролировать, когда память распределяется?

1 голос
/ 13 октября 2011

C рассматривается как высокоразвитый низкоуровневый язык, в основном, malloc используется в динамических массивах, который является ключевым компонентом в стеке и очереди.для других языков, которые скрывают часть указателя от разработчика, не вполне способны выполнять аппаратное программирование.

1 голос
/ 13 октября 2011

Возможно, вопрос должен звучать так: «Зачем вам нужно что-то вроде int array[n], когда вы можете использовать указатели?»

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

Но настоящий ответ таков: «Вот так».Возможны другие варианты, и доказательство тому, что есть другие языки, которые делают другие вещи (и даже C99 допускает разные вещи).

0 голосов
/ 13 октября 2011

C - это скомпилированный язык, а не интерпретируемый. Если вы не знаете n во время компиляции, как компилятор должен создавать двоичный файл?

...