我是C编程语言的初学者。我有点理解堆栈内存、堆内存、malloc、指针和内存地址的一般定义。但我有点不知所措,不知道什么时候在实践中使用每种技术,以及它们之间的区别。
我写了三个小程序作为例子。他们都做同样的事情,我想对他们之间的区别做一点评论和解释。我确实意识到这是一个幼稚的编程问题,但我希望在这里连接一些基本点。
Program 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();
}

Program 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();
}

Program 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)?在这种情况下,为什么不把它设为全局变量呢?

最佳答案

我有点理解堆栈内存的一般定义,堆
内存、malloc、指针和内存地址。。。我想要一点
关于它们之间的区别的评论和解释
是。。。
程序1在堆栈上为变量netWorth分配内存,并且
使用指向此堆栈内存地址的指针直接修改
变量netWorth。这是按引用传递的示例。
问:程序2。。。worthRef的本地副本在返回时是否被销毁?
答:int netWorth只存在于()的范围内,其中包含了调用()。
程序1和程序3。。。一种是传递指向堆栈变量的指针,另一种是传递指向堆变量的指针。
问:但在这种情况下,我为什么还需要堆呢?
A:你没有。像在程序1中那样,简单地取addressof(&)in t是完全可以的(可以说是更可取的)。
问:堆允许程序员选择变量的生存期,对吧?
A:是的,这是动态分配内存的一个方面。你是对的。
问:在这种情况下,为什么不把它作为一个全局变量呢?
A:是的,那是另一种选择。
任何问题的答案“为什么选择一种设计方案而不是另一种?”通常是“视情况而定”。
例如,您可能不能只声明所有的“局部变量”,因为您所在的环境正好有一个非常小的、有限的堆栈。它发生了:)
一般来说,
如果可以声明一个局部变量而不是分配堆,通常应该这样做。
如果可以避免声明全局变量,通常应该这样做。

09-28 09:16