了解动态分配通过引用传递参数
Posted
技术标签:
【中文标题】了解动态分配通过引用传递参数【英文标题】:understand passing parameters by reference with dynamic allocation 【发布时间】:2011-05-08 17:19:00 【问题描述】:我正在尝试了解如何在 C 语言中通过引用传递参数。 所以我写了这段代码来测试参数传递的行为:
#include <stdio.h>
#include <stdlib.h>
void alocar(int* n)
n = (int*) malloc( sizeof(int));
if( n == NULL )
exit(-1);
*n = 12;
printf("%d.\n", *n);
int main()
int* n;
alocar( n );
printf("%d.\n", *n);
return 0;
这里是打印出来的:
12. 0。示例 2:
#include <stdio.h>
#include <stdlib.h>
void alocar(int* n)
*n = 12;
printf("%d.\n", *n);
int main()
int* n;
n = (int*) malloc(sizeof(int));
if( n == NULL )
exit(-1);
alocar( n );
printf("%d.\n", *n);
return 0;
打印出来了:
12. 12.这两个程序有什么区别?
【问题讨论】:
指针不是整数。您的格式说明符应该是%p
,而不是%d
。在您的第一个示例中(现在您已了解原因),n
从未初始化,因此使用它会给您带来未定义的行为。任何事情都有可能发生。
关于未初始化的指针是正确的,但格式说明符本身在这些示例中是正确的。
【参考方案1】:
C 是按值传递,它不提供按引用传递。 在您的情况下,指针(不是它指向的内容)被复制到函数参数(指针按值传递 - 指针的值是地址)
void alocar(int* n)
//n is just a local variable here.
n = (int*) malloc( sizeof(int));
//assigning to n just assigns to the local
//n variable, the caller is not affected.
你想要这样的东西:
int *alocar(void)
int *n = malloc( sizeof(int));
if( n == NULL )
exit(-1);
*n = 12;
printf("%d.\n", *n);
return n;
int main()
int* n;
n = alocar();
printf("%d.\n", *n);
return 0;
或者:
void alocar(int** n)
*n = malloc( sizeof(int));
if( *n == NULL )
exit(-1);
**n = 12;
printf("%d.\n", **n);
int main()
int* n;
alocar( &n );
printf("%d.\n", *n);
return 0;
【讨论】:
我想这是一个观点问题,但我会说地址运算符可以通过引用传递值。 @Christoffer:这是一个事实上的术语,但它仍然是一个值。 这是真的。 C 不支持按引用传递。所以实际上我没有将地址传递给“aloca”,因为 n 不存储地址。 @adriano ,您确实将地址传递给 alloca,'n' 存储一个地址(但它不是 TO 'n' 的地址)alloca 收到该地址的副本,但更改副本不会t 更改原件。但是和第二个例子一样,你可以传递 'n' 的地址,允许 alloca 改变 main 中的 'n'。【参考方案2】:其实差别不大,只是第一个坏了。 :)(嗯,两者都是,但第一个更坏)。
让我解释一下第二种情况会发生什么:
pointer-to-int
类型的变量 n
在堆栈上分配
一个int
类型的新变量被分配到栈中,它的地址存储在变量n
中
函数alocar
被调用,传递变量n
的副本,这是我们int
类型变量地址的副本
该函数将n
指向的int
变量设置为12
该函数打印n
(12) 所指向的变量的值
函数返回
第一种情况:
pointer-to-int
类型的变量 n
在堆栈上分配
函数 alocar
使用变量 n
的副本调用(该变量仍未初始化 - 包含未知值)
在内存中创建了一个 int
类型的新变量,并将函数 alocar
中变量 n
的本地副本设置为指向该新变量
变量(由函数的 n
的本地副本指向)设置为 12 并打印
函数返回,再次在 main() 函数中:
由于main中原来的n
变量还没有初始化,它指向内存中的一个随机位置。因此打印内存中随机位置的值(这可能会使您的程序崩溃)。
另外,这两个程序都被破坏了,因为它们没有释放 malloc() 分配的内存。
【讨论】:
我知道这需要释放分配的内存。我通常释放它。我明白你的解释。你是对的。非常感谢!!! 很高兴我提供了帮助 :),还请记住,在 SE 上,每次您回答问题时,在您最喜欢的答案旁边打勾是礼貌的,以表明问题已解决(并获得一些美味的分数,高兴!:))。【参考方案3】:你想修改main
中n
的值,而不是n
所指向的,所以你需要传递一个指向它的指针。由于main
中n
的类型是int *
,所以alocar
的参数需要是int **
类型:
void alocar(int **n)
*n = malloc(sizeof **n); // note no cast, operand of sizeof
if (!*n)
exit(-1);
**n = 12;
printf("%d\n", **n);
int main(void)
int *n;
alocar(&n);
printf("%d\n", *n); // we've already tested against n being NULL in alocar
free(n); // always clean up after yourself
return 0;
【讨论】:
【参考方案4】:nos发布的答案是正确的。
另外请注意,当 main() 中的 printf 行尝试取消引用 main 的指针 n
(从未设置)时,两个发布程序中的第一个实际上会在许多系统上崩溃:
printf("%d.\n", *n);
【讨论】:
【参考方案5】:看看,第一个程序发生了什么。
在调用 alocar 之前,我们在 main 中只有变量 n,指向一些未定义的地方:
main()::n [ X--]--->(?)
(方括号中的值,未定义,标记为X)。然后我们调用 alocar,我们在 alocar 的作用域中有另一个变量,它有一个 origianl var 的副本。
main()::n [ X--]--->(?)
alocar()::n [ X--]-----^
现在,分配一些内存:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ Y ]
为分配的变量赋值:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ 12 ]
返回。 alocar()::n 仅在执行 alocar() 时才会被移除。
main()::n [ X--]--->(?)
[ 12 ]
main()::n 仍然指向某个未定义的位置...(可能存储值 0)并且没有人指向分配的位置。
【讨论】:
以上是关于了解动态分配通过引用传递参数的主要内容,如果未能解决你的问题,请参考以下文章