2013-11-27 3 views
0

두 개의 다른 구조체를 함수에 전달하는 방법을 알아야합니다. 멤버다른 구조체를 함수에 전달 (void * 사용)

warning: dereferencing 'void *' pointer 
error: request for member left in something not a structure or union 

같은 오류가 바로 여기

내가 (코드는 컴파일되지 않을 수 있음) 일반적인 용어로 무슨 짓을 : 나는 매개 변수에 대한 무효 *를 사용하지만 난이 오류가 발생하고 시도했다.

struct A{ 
    char *a; 
    struct A *left, *right; 
} *rootA; 

struct B{ 
    char *b; 
    struct B *left, *right; 
} *rootB; 

void BinaryTree(void *root, void *s){ 
    if(condition) 
     root->left=s; 
    else if(condition) 
     BinaryTree(root->left, s); 

    if(condition) 
     root->right=s; 
    else if(condition) 
     BinaryTree(root->right, s); 
} 

int main(){ 
    // Assume the struct of nodeA and nodeB get malloc() 
    // as well as the variables a and b with actual data. 
    struct A nodeA; 
    struct B nodeB; 
    BinaryTree(rootA, nodeA); 
    BinaryTree(rootB, nodeB); 

    return 0 
} 
+2

코드는 포인터를 전달하고 있지 않음을 나타냅니다. 'BinaryTree (rootA, & nodeA)'등을 의미 했습니까? – lurker

+0

nodeA와 nodeB의 메모리 위치를 전달 중입니다. 함수의 매개 변수에있는 void 포인터는 함수 no에서 사용할 수 있도록 역 참조해야합니다. – user2644819

+0

매개 변수 유형은 포인터입니다. 구조체에 대한 포인터가 아니라 전체 구조체를 전달하고 있습니다. 물론 그 이상의 문제가있을 수 있습니다. 컴파일러는 구조체를 void 포인터로 "역 참조"하지 않습니다. – lurker

답변

0

구조체 선언에 혼동을 느낍니다. 유형은 struct 다음에 나오는 단어로 제공됩니다. 결국 typedef에 대해 알기 전까지는 끝내야합니다. 예 :

struct A{ 
char *a; 
struct A *left, *right; 
}; 

BinaryTree를 호출 할 때는 항상 struct가 아닌 포인터를 전달해야합니다. 예 :

BinaryTree(&nodeA, &nodeA); 

void 포인터에 대한 작업을 수행 할 때는 먼저 올바른 포인터 유형으로 변환해야합니다. 예 :

(struct A*)root->left=s; 

무효가 포인터 주위에 이러한 구조체를 전달은 확실히 나쁜 관행이고 당신은 자신을 끔찍하게 혼란스러워 할 것이다. 보이드 포인터는 드물게 사용됩니다. C에서 시작하는 것 같으므로 가치와 참조 의미를 조금 더 잘 이해할 때까지는 사용하지 않는 것이 좋습니다. 그 말은, 내가 C로 시작할 때 나는 많은 어리석은 코드를 만들었다. 당신은 시간과 실천으로 그것을 알아낼 것입니다.

+0

끝에있는 것은 단순히 정의 된'struct'의 변수를 선언합니다. 즉'struct A {...} * rootA;'는'struct A'를 정의하고 변수'rootA'를'struct A '. 'typedef'와 함께 사용될 때에 만'rootA'가 타입으로 정의됩니다. 두 인수로'nodeA'를 사용하면 루트와 노드로 nodeA를 사용하고자 함을 의미합니다. OP의 의도는 아닙니다. 또한'struct A'가'typedef'되지 않았기 때문에'(A *) '에 대한 캐스트는 유효하지 않습니다. – Kninnug

+0

사실,하지만 OP에서 그런 식으로 사용하지 않을 수도 있습니다. 왜 이런 상황에서이 구조체의 로컬 인스턴스와 글로벌 인스턴스를 모두 가질 수 있습니까? –

+1

글로벌 (노드가 아닌)의 루트를 선언하는 것이 그렇게 이상하지 않습니다. 그리고 당신은 root와 node 모두'nodeA '를 사용하고 싶어한다는 것을 의미합니다. 운영자는'nodeA'와'nodeB'가 이제 스택에 할당되고 트리에있는 동안 범위를 벗어날 수 있음을주의해야합니다. – Kninnug

0

재검토해야 할 프로그램의 두 가지 측면이 있습니다. 하나는 값으로 전달하는 참조가 아닌 전달하는 매개 변수입니다. 따라서, BinaryTree 함수의 호출은 당신이 BinaryTree 기능에서 이러한 무효 포인터를 처리하는 방법 다른 주요 고려 사항이다

BinaryTree(rootA, &nodeA); 

해야한다. 현재의 형태에서, 여기 root

void BinaryTree(void *root, void *s){ 
    if(condition) 
     root->left=s; 

void * 따라서, root->left 평가 될 수 없다. 따라서, 당신은 또 하나의 중요한 고려 사항은 당신이 다른 구조에 대한 동일한 기능을 사용하는 것입니다, 심지어이 방법으로

struct A *hdl = (struct A*)(root); 
hdl->left = s; 

같은 의미있는 데이터 유형에 배역root해야합니다. 따라서 root을 언제 AB으로 입력해야하는지 알기가 어렵거나 어려울 수 있으므로이 전략을 다시 생각해 볼 필요가 있습니다.

+1

'void *'가 자동으로 승격되기 때문에 캐스트를 사용하면 캐스트가 필요하지 않습니다. 'root '가 사용 가능한 데이터 유형에 할당하지 않고 사용 된 경우, 멤버에 액세스하기 전에 캐스팅되어야합니다. – Kninnug

+0

@Kninnug ... 예, 동의합니다. 나는 가독성을 위해 그것을 보관하고'void *'가 좀 더 의미있는 데이터 타입 포인터로 변환되어야한다는 점을 강조했다. – Ganesh

관련 문제