我正在尝试了解如何通过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.
这两个项目有什么不同?
答案 0 :(得分:6)
C是按值传递,它不提供传递引用。 在你的情况下,指针(不是它指向的)被复制到函数paramer(指针通过值传递 - 指针的值是一个地址)
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;
}
答案 1 :(得分:3)
实际上并没有太大区别,除了第一个被打破。 :)(嗯,两者都是,但第一个更多的是打破了。)
让我解释第二种情况会发生什么:
n
的变量pointer-to-int
在堆栈上分配int
类型的新变量分配给堆栈,它的地址存储在变量n
alocar
,传递变量n
的副本,该副本是int
int
指向的n
变量设置为12 n
(12)第一种情况:
n
的变量pointer-to-int
在堆栈上分配alocar
的副本调用函数n
(它仍然未初始化 - 包含未知值)int
的新变量,并将函数n
中的变量alocar
的本地副本设置为指向该新变量n
指向)设置为12并打印n
变量仍然未初始化,因此它指向内存中的随机位置。因此打印内存中随机位置的值(这可能会导致程序崩溃)。此外,两个程序都被破坏,因为它们没有释放malloc()分配的内存。
答案 2 :(得分:1)
您希望修改n
中main
的值,而不是n
指向的值,因此您需要传递一个指向它的指针。由于n
中的main
类型为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;
}
答案 3 :(得分:0)
nos发布的答案是正确的。
另请注意,当main()中的printf行试图取消引用从未设置的主指针n
时,两个发布的程序中的第一个实际上会在许多系统上崩溃:
printf("%d.\n", *n);
答案 4 :(得分:0)
看,第一个项目发生了什么。
在调用alocar之前,我们在main中只有变量n,指向一些未定义的位置:
main()::n [ X--]--->(?)
(方括号中的值,未定义,标记为X)。然后我们调用alocar,我们在alocar的范围内有另一个变量,它有一个origianl var的副本。
main()::n [ X--]--->(?)
alocar()::n [ X--]-----^
现在,分配一些内存:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ Y ]
将值分配给已分配的var:
main()::n [ X--]--->(?)
alocar()::n [ *--]--->[ 12 ]
返回。 alocar():: n只在执行alocar()时才被删除。
main()::n [ X--]--->(?)
[ 12 ]
main():: n仍指向某个未定义的位置...(可能存储值0)并且没有人指向分配的位置。