Передача по ссылке и использование malloc - PullRequest
1 голос
/ 24 марта 2019

Я новичок в языке программирования Си.Я вроде понимаю общее определение стековой памяти, кучи памяти, malloc, указателей и адресов памяти.Но я немного ошеломлен пониманием того, когда использовать каждую технику на практике, и разницей между ними.

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

Программа 1 :

void B (int* worthRef) {
  /* worthRef is a pointer to the
     netWorth variable allocated
     on the stack in A.
  */
  *worthRef = *worthRef + 1;
}

void A() {
  int netWorth = 20;
  B(&netWorth);

  printf("%d", netWorth);  // Prints 21
}

int main() {
  A();
}

Программа 2:

int B (int worthRef) {
  /* worthRef is now a local variable. If
     I return it, will it get destroyed
     once B finishes execution?
  */
  worthRef = worthRef + 1;
  return (worthRef);
}

void A() {
  int netWorth = 20;
  int result = B(netWorth);

  printf("%d", result);  // Also prints 21
}

int main() {
  A();
}

Программа 3 :

void B (int* worthRef) {
  /* worthRef is a pointer to the
     netWorth variable allocated on
     the heap.
  */
  *worthRef = *worthRef + 1;
}

void A() {
  int *netWorth = (int *) malloc(sizeof(int));
  *netWorth = 20;

  B(netWorth);

  printf("%d", *netWorth);  // Also prints 21

  free(netWorth);
}

int main() {
  A();
}

Пожалуйста, проверьте мое понимание:

  • Программа 1 выделяет память в стеке для переменной netWorth и использует указатель на этот адрес стековой памяти, чтобы напрямую изменить переменную netWorth.Это пример передачи по ссылке.Копия переменной netWorth не производится.
  • Программа 2 вызывает B(), что создает локально сохраненную копию значения netWorth в ее стековой памяти , увеличивает эту локальную копию, а затем возвращает ее к A() как result.Это пример передачи по значению.
    • Локальная копия worthRef уничтожается при возвращении?
  • Программа 3 выделяет память в куче для переменной netWorth, переменная, и использует указатель на этот адрес памяти кучи, чтобы напрямую изменить переменную netWorth.Это пример передачи по ссылке.Копия переменной netWorth не производится.

Моя основная путаница заключается в том, что между Программой 1 и Программой 3. Обе имеют указатели;просто один передает указатель на переменную стека, а другой передает указатель на переменную кучи, верно?Но в этой ситуации зачем мне вообще куча?Я просто хочу иметь единственную функцию для непосредственного изменения одного значения, что я могу сделать без проблем malloc.

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

Ответы [ 2 ]

1 голос
/ 24 марта 2019

Проверка вашего понимания:

  • Программа 1 выделяет память на в пределах фрейма стека функций A() для переменной netWorth и передает адрес netWorth в качестве указателя на этот стек адрес памяти вфункция B() позволяет B() до напрямую изменять значение для переменной netWorth , хранящейся по этому адресу памяти .Это пример передачи по ссылке с передачей «адреса» переменной по значению .(нет передачи по ссылке в C - это все передача по значению) Копия переменной netWorth не производится.
  • Программа 2 вызывает B(), которая создает локально сохраненную копию значения netWorth наего стековая память увеличивает эту локальную копию, а затем возвращает целое число обратно в A() как результат.( функция всегда может возвращать свой собственный тип ) Это пример передачи по значению (, поскольку в C есть только передача по значению).

(Уничтожается ли локальная копия worthRef при возвращении? - ответьте да, но поскольку функция всегда может возвращать свой собственный тип, она может вернуть значение int в A() [чтообрабатывается соглашением о вызовах для платформы])

  • Программа 3 выделяет память в куче для переменной netWorth и использует указатель на эту кучу адрес памяти для прямого изменения переменной netWorth.В то время как "стек / куча" являются обычно используемыми терминами, C не имеет понятия о стеке или куче, однако, переменные объявляются с Длительность автоматического хранения который ограничен областью, в которой они объявлены - или - при выделении с помощью malloc/calloc/realloc, блок памяти имеет Длительность выделенного хранилища что хорошо для жизни программы или пока блок памяти не будет освобожден.(здесь также имеются значения static и thread local продолжительности хранения). См .: C11 Standard - 6.2.4 Продолжительность хранения объектов Это пример передачи по ссылке. ( Все это передается по значению! ) Копия переменной netWorth не производится. Указатель на адрес, первоначально возвращенный malloc, используется повсюду для ссылки на эту область памяти .
1 голос
/ 24 марта 2019

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

<= OK ... </em>

Программа 1 выделяет память в стеке для переменной netWorth и использует указатель на этот адрес памяти стеканапрямую изменить переменную netWorth.Это пример передачи по ссылке.

<= Абсолютно правильно! </em>

В: Программа 2 ... Есть ли локальная копияУничтожение worthRef при его возвращении?

A: int netWorth существует только в пределах A (), включая вызов B ().

Программа1 и программа 3 ... один передает указатель на переменную стека, а другой передает указатель на переменную кучи.Q: Но в этой ситуации зачем мне куча?

A: Нет.Вполне нормально (возможно предпочтительно ) просто взять addressof (&) int, как вы это делали в Программе 1.

Q: куча позволяет программисту выбирать время жизнипеременная, верно?

A: Да, это один из аспектов динамического распределения памяти.Вы правы.

В: Почему бы просто не сделать ее глобальной переменной в этом случае?

A: Да, это еще одна альтернатива.

Ответ на любой вопрос "Почему стоит выбрать один вариант дизайна вместо другого?"обычно "это зависит".

Например, может быть, вы не можете просто объявить все "локальные переменные", потому что ваша среда имеет очень маленький, ограниченный стек.Это происходит:)

В общем,

  1. Если вы можете объявить локальную переменную вместо выделения кучи, вам, как правило, следует.

  2. Если вы можете избежать объявления глобальной переменной, вам, как правило, следует:

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