Я не уверен, что весь этот разговор о «куче» и «стеке» урезан до глубины языка, поэтому позвольте мне попробовать что-то более внутреннее.
Ваша первая версия использует только автоматическое распределение, что означает, что все переменные имеют автоматическое время жизни. То есть все переменные заканчивают свою жизнь в конце своей охватывающей области: myFunction
создает локальную переменную типа struct person
и возвращает копию этой переменной; функция main
объявляет локальную переменную того же типа и присваивает ей результат вызова функции. В конце каждой области видны и локальные переменные.
Вторая версия использует динамическое или ручное распределение . Вы явно выделяете хранилище для переменной person
с помощью вызова malloc()
, и это хранилище будет выделяться до тех пор, пока кто-то не освободит (через free()
). Поскольку вы никогда не освобождаете его, это фактически утечка памяти.
Принципиальным отличием является срок службы и ответственность .
Несколько плюсов и минусов: автоматическое распределение означает, что ответственность является локальной, и вам, как правило, не о чем беспокоиться. Однако это достигается ценой необходимости копировать аргументы и возвращать значения по значению, что может быть дорогостоящим или нежелательным. Выделение вручную позволяет ссылаться на большие объемы памяти с помощью простого и дешевого указателя и часто является единственным способом реализации определенных конструкций, но несет бремя того, чтобы автор помнил, кто за какой ресурс отвечает.