2010-11-11 106 views
1

我想了解如何通过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. 

Wha t是这两个程序的区别?

+0

指针不是整数。你的格式说明符应该是'%p',而不是'%d'。在你的第一个例子中(现在你明白了为什么),'n'永远不会被初始化,所以使用它会给你一个未定义的行为。什么事情都可能发生。 – GManNickG 2010-11-11 20:46:16

+0

正确的单位化指针,但格式说明符本身在这些示例中是正确的。 – Kos 2010-11-12 13:37:00

回答

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; 
} 
+0

我想这是一个问题,但我会说地址运算符可以通过引用传递值。 – Christoffer 2010-11-11 20:58:29

+0

@Christoffer:这将是一个事实上的术语,但它仍然是一个价值。 – GManNickG 2010-11-11 21:03:34

+0

这是真的。 C不支持通过引用。所以实际上我不会把地址传给'aloca',因为n没有存储地址。 – adriano 2010-11-11 21:29:48

3

其实算不上多大的差别,除了第一个被打破了。 :)(好吧,都是,但第一个是更多)。

让我解释一下在第二种情况下会发生什么:

  • 变量pointer-to-intn
  • int类型的新变量被分配到堆栈中的栈上分配,它的地址存储在变量n
  • 功能alocar被调用,通过变量n的副本,这是我们的变量的地址的副本int
  • 函数设置int变量被指向通过n至12
  • 功能打印的变量由n(12)指出的值
  • 该函数返回

第一种情况:

  • 可变pointer-to-int类型的n被分配在堆栈上
  • 功能alocar被称为与可变n的副本(这仍然是未初始化 - 包含未知的值)
  • int类型的新变量在内存中创建和可变n的在功能alocar本地副本被设置
  • 由于原n变量:以指向新的变量
  • 变量(由函数的本地的n拷贝指出)在main()函数设置为12和印刷
  • 函数返回时,再次在主要仍然是itialized,它指向一个随机的地方在记忆中。所以打印内存随机位置的值(这可能会导致程序崩溃)。

此外,两个程序都被破坏,因为它们没有释放由malloc()分配的内存。

+0

我知道这是需要释放分配的内存。我通常免费它。我理解你的解释。你是对的。非常感谢!!! – adriano 2010-11-11 21:20:05

+0

很高兴我帮助了:),请记住,在SE上,每次有问题回答时,请在您最喜欢的答案旁边打勾绿色标记,以表明问题已解决(并分数点美味点, !:))。 – Kos 2010-11-12 13:35:53

0

nos发布的答案是正确的。

还要注意,第一二公布的方案实际上会崩溃,在许多系统中,当在main()中的printf行试图取消引用主要的指针n,这是从来没有设置:

printf("%d.\n", *n); 
1

你想修改n的值main,而不是n指向,所以你需要传递一个指针给它。由于nmain类型是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; 
} 
0

见,发生了什么事的第一个程序。

调用之前alocar我们刚才变量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)并且没有人指向分配的地方。