我是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:是的,那是另一种选择。
任何问题的答案“为什么选择一种设计方案而不是另一种?”通常是“视情况而定”。
例如,您可能不能只声明所有的“局部变量”,因为您所在的环境正好有一个非常小的、有限的堆栈。它发生了:)
一般来说,
如果可以声明一个局部变量而不是分配堆,通常应该这样做。
如果可以避免声明全局变量,通常应该这样做。