2016-08-10 110 views
1

以下程序有兩種結構。我不明白我怎麼可以從一個結構變量的值傳遞到另一個結構體變量,而使用指針兩種結構如何以這種方式工作

#include <stdio.h> 

typedef struct { 
int c; 
char d; 
}bob; 

typedef struct { 
int c; 
char d; 
}anna; 

//expecting 'bob' type variable 
void fun(bob *var2) 
{ 

printf("var2->c=%d\n",var2->c); 
printf("var2->d=%c\n",var2->d); 

} 

int main() 

{ 
anna var1; 
var1.c=2; 
var1.d='c'; 
fun(&var1);//passing 'anna' type pointer 
return 0; 
} 

...但如果我更改程序使用普通的變量傳遞值,它使編譯錯誤。

#include <stdio.h> 

typedef struct { 
int c; 
char d; 
}bob; 

typedef struct { 
int c; 
char d; 
}anna; 

//expecting a variable of type 'bob' 
void fun(bob var2) 
{ 

printf("var2.c=%d\n",var2.c); 
printf("var2.d=%c\n",var2.d); 

} 

int main() 

{ 
anna var1; 
var1.c=2; 
var1.d='c'; 
fun(var1);//passing a variable of type 'anna' 
return 0; 
} 

這是什麼邏輯?

回答

1

首先,第一個版本,確實提醒你。啓用合適的編譯器選項,你會看到

source_file.c:在函數 '主':
source_file.c:30:5:警告:從兼容的指針類型
傳遞的 '樂趣' 參數1

fun(&var1);//passing 'anna' type pointer 
^ 

source_file.c:16:6:注:應爲 '結構鮑勃*',但參數的類型爲 '結構安娜*'

void fun(bob *var2) 

這就是說,在代碼

的第一版本//期待 '鮑勃' 型變量

是錯誤!其應該是(遵循強調

//期待一個指針 '鮑勃' 型變量

作爲的每個C規則,指針到類型可以是轉換爲另一種類型,但結果並不總是被定義。所以,第一個版本的代碼編譯器(帶有警告)並運行。

OTOH,在第二種情況下,annabob是不同的類型,所以在傳遞參數和接收參數時不可能進行互換。對於編譯器來說,它們是不同的類型,編譯器會相應地運行。

1

回答初學者/中間經歷:

任何兩個結構類型與不同類型名C是不兼容的類型。無論他們是否碰巧有相同的成員變量。同樣,指向不同結構類型的指針也不兼容。所以你的類型「bob」和「anna」是不兼容的,像你一樣使用它們在形式上是不安全的,也沒有明確定義。

只要不要這樣做,你最終會寫出微妙的錯誤。


答案老兵:

儘管上述類型兼容性規則,C(而不是C++)允許一些技巧,讓你在幾個不同的方式使用一個存儲區域,無論類型的變量存儲在那裏。這被稱爲「類型雙關」。大多數情況下鍵入雙關語是通過union完成,例如:

typedef struct 
{ 
    bob b; 
    anna a; 
} bobanna; 

如果你會使用一個指針類型類似上面的,你實際上是在允許承擔,要麼這兩種類型都可以使用,但只是因爲在這種情況下,所有涉及的結構/聯合成員都包含(遞歸)相同的類型。例如,這樣的代碼很好:

void fun (bobanna *var) 
{ 
    bob* b = var.b; 
    b.c = something; 
} 

bobanna ba = {.anna.c = 1 }; 
fun(&ba); 

請注意,類型戳是一個高級主題。以這樣的方式做錯事很容易 - 如果您還不知道指針別名the strict aliasing rule,我不會推薦考慮上述技巧。