2011-08-19 113 views
0

我正从C++将我的一个项目转变为C,而且事情一直很顺利,因为我没有使用很多C++功能开始。但是我遇到了一个奇怪的问题,我在一个小测试程序中设法复制。这对我没有意义,所以我会尝试用代码解释。函数层次结构和C指针初始化问题

typedef struct foo 
{ 
    int num1; 
    float num2; 
    char* name; 
}foo; 

//This function allocates and initializes a foo object 
foo* Initfoo() 
{ 
    foo* f = malloc(sizeof(foo)); 
    f->num1 = 1024; 
    f->num2 = 3.14; 

    f->name = malloc(100); 
    strcpy(f->name,"eleos re paidia"); 

    //Just before returning here by checking the f pointer we can see 
    // it is initialized correctly 
    return f; 
} 



void afunctest(foo* f) 
{ 
    ///... suppose this function does stuff before ... 

    //here it initializes the foo pointer 
    f = Initfoo(); 
    ///...and after here suppose the function also does more stuff.. 

    //by checking at this point in the program the pointer is still initialized 
    //correctly to what InitFoo initialized it to 
    int asd =5; 
} 


int main() 
{ 

    foo* f = 0; 

    //should do stuff and also initialize the foo* f 
    afunctest(f); 

    //when we check here the pointer f is still 0 as if afunctest() function never ran 
    int asd = 5; 

    return 0; 
} 

所以基本上用几句话来说,我们声明一个foo指针并将其初始化为零。然后,我们将该指针传递给afunctest()函数,该函数应该执行某些操作并将其初始化以备后用。在afunctest()函数内,它似乎被正确初始化,但一旦我们回到main(),它仍然具有0的值,就好像该函数从未运行过一样。

起初我以为这是我原来的程序中一个非常复杂的错误,因为它已经变得相当复杂,但能够在这里复制意味着我错过了C语言中与C++相比使用指针的基础知识。你可以指出吗?我究竟做错了什么?提前感谢任何反馈。

P.S:我的编译器是在Windows 7

+1

我敢打赌,你对应的C++函数具有不同的签名,或者它也在那里不行... – sth

回答

2

你正在改变当地的f副本GCC。这对呼叫者没有影响。

void afunctest(foo* f) 
{ 
    f = Initfoo(); /* No effect for the caller of afunctest 
} 

尝试是这样的:

void afunctest(foo **f) 
{ 
    /* ... */ 
    *f = Initfoo(); 
} 

/* In main. */ 
foo* f = 0; 
functest(&f); 

顺便说一下,也就是一个C FAQ: Pass pointer Init

+0

哦,所以C总是传递价值。这很好。然后有很多代码来检查类似的错误。谢谢你现在有道理。 – Lefteris

+0

谢谢。正如您所说,常见问题解答也可以解释它。感觉真的很愚蠢,我不知道这一点。 – Lefteris

+0

@Lefteris:请注意,这与C++中的相同。如果您明确指定参数是引用(带有&&),则C++仅通过引用传递。通常C++引用更像是指针而不是原始值,所以'foo *&f'参数通常会转换为'foo ** f'而不是'foo * f'。 – sth

1

C通过的值。如果您想要从afunctest()内更改f,您需要将指针传递给它并操纵它指向的值。

例如:

#include <stdio.h> 

static void fn (int x, int *y) { 
    x = 42;  // Changes local copy of x, doesn't affect a. 
    *y = 42; // Changes value *pointed to* by local y (which is b in caller). 
} 

int main (void) { 
    int a = 1; 
    int b = 1; 
    fn (a, &b); // Pass a and *address of* b. 

    printf ("%d %d\n", a, b); 
    return 0; 
} 

结果输出:

1 42 

在你的代码而言,这将是:

void afunctest (foo **f) { 
    *f = Initfoo(); 
} 

int main (void) { 
    foo* f = 0; 
    afunctest (&f); 
    return 0; 
} 
+0

哦,所以C总是传递价值。这很好。然后有很多代码来检查类似的错误。谢谢你现在有道理。 – Lefteris

1

该解决方案实际上是安静直截了当 - 记住C总是按值传递,所以当你在func函数中设置f时,f不会更新你的f他的主要功能。

要做到这一点,你需要使用**˚F像这样:

void afunctest(foo** f) 
{ 

    //here it initializes the foo pointer 
    *f = Initfoo(); 

} 

,并调用它像这样:

int main() 
{ 

    foo* f = 0; 

    //should do stuff and also initialize the foo* f 
    afunctest(&f); 

    return 0; 
} 
+0

感谢您的回答。现在有道理。必须检查我的所有代码,然后检查传递指针的函数层次结构。 – Lefteris