2013-11-27 45 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後面的字給出。最後這件事需要去做,至少在你瞭解typedefs之前。例如:

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

當您調用BinaryTree時,您需要始終通過指針而不是結構。示例:

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

聲明樹全局的根(但不是節點)並不奇怪。你似乎暗示他希望使用'nodeA'作爲根和節點。雖然OP應該注意'nodeA'和'nodeB'現在分配在堆棧上,並且在它們仍然在樹中時可能超出範圍。 – Kninnug

0

您的程序有兩個方面需要重新審視。一,是參數通過你傳遞的值而不是引用。因此,爲BinaryTree函數調用應該有

BinaryTree(rootA, &nodeA); 

的另一個主要考慮的是你如何處理在BinaryTree這些函數void指針。在當前形式中,

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

這裏rootvoid *,因此,root->left不能評價。因此,你需要類型轉換root到有意義的數據類型一樣

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

即使使用這種方法,一個更重要的考慮是,你正在使用不同的結構相同的功能。因此,知道何時輸入root作爲AB是困難的/具有挑戰性的,因此,這種策略需要小範圍的反思。

+1

由於'void *'會自動提升,所以賦值不需要強制轉換。如果使用'root'而不將其分配給可用的數據類型,則必須在訪問成員之前進行強制轉換。 – Kninnug

+0

@Kninnug ...是的,我同意。我保持它的可讀性,並強調'void *'應該被轉換爲更有意義的數據類型指針。 – Ganesh