2011-08-19 5 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 포인터를 선언하고 그것을 0으로 초기화합니다. 그런 다음 afunctest() 함수에 해당 포인터를 전달합니다.이 함수는 필요한 작업을 수행하고 나중에 사용하기 위해 초기화해야합니다. afunctest() 함수 안에는 올바르게 초기화 된 것처럼 보이지만 main()으로 돌아 가면 함수가 실행되지 않은 것처럼 여전히 0 값을 갖습니다.

처음에는 복잡한 프로그램 이었기 때문에 원래 프로그램에서 정말 복잡한 버그라고 생각했지만 여기에 그것을 복제 할 수 있다는 것은 C++에 비해 C에서 포인터 사용법에 대한 근본적인 것이 빠져 있음을 의미합니다. 당신은 사람들이 그것을 지적 할 수 있습니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까? 피드백에 대해 미리 감사드립니다.

P.S : 제 컴파일러는 당신은 f의 로컬 사본을 변경

+1

를 ++ 함수는 다른 서명이, 나 또한 거기에서 일하지 않을 것입니다 ... – sth

답변

2

윈도우 7에서 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는 값으로 전달됩니다.fafunctest()에서 변경하려면 포인터을 전달하고 해당 포인터가 가리키는 값을 조작해야합니다. 것 당신이 가지고있는 코드의 관점에서

1 42 

: : 출력에

#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; 
} 

결과 : 예를 들어

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

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

오, 그래서 C는 항상 가치에 의해 지나간다. 그거 알아두면 좋을거야. 비슷한 실수를 확인하는 코드가 많이 있습니다. 지금은 감사합니다. – Lefteris

1

이 솔루션은 실제로 조용 똑바로 앞으로 - C는 항상 값으로 전달되므로 f를 t에서 업데이트하지 않는 afunctest 함수에서 f를 설정하면 기억하십시오. 그는 주요 기능.

void afunctest(foo** f) 
{ 

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

} 

등과 같이 호출 :과 같이 f를

이 ** 사용하기 위해 필요한이 작업을 수행하려면 나는 당신의 해당 C를 내기

int main() 
{ 

    foo* f = 0; 

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

    return 0; 
} 
+0

답변 해 주셔서 감사합니다. 지금은 의미가 있습니다. 내 코드를 모두 확인한 다음 포인터를 전달하는 함수 계층 구조를 확인하십시오. – Lefteris