2011-02-23 35 views
6

使用的typedef爲了在C中定義一個新的數據類型,例如一個類型鏈表
一個可以使用下面的定義使用指針用C

struct list_node { 
    int x; 
    struct list_node * next; 
}; 

//1 
typedef struct list_node list1; 
//2 
typedef struct list_node *list2; 

的一個從我目前掌握的時候結構或不看到常見的做法是第一個定義。

問題是如果第二個定義也是可接受的做法。 在哪些情況下,如果有人喜歡第一個? 假設我們使用的變量是指向struct list_node 的指針,可以對兩種類型執行相同的操作嗎? 第一個的優點是什麼?

+0

類似的問題:http://stackoverflow.com/questions/3781932/is-typedefing-a-pointer-type-considered-bad-practice – 2011-02-24 00:03:17

+0

或兩者都不... :) – alternative 2011-02-24 00:16:56

回答

5

我會要求API用戶鍵入「*」,即typedef結構,而不是指向結構的指針。這是GLib中廣泛使用的風格,它是更受歡迎的C棧之一。

它工作得很好,因爲它重要的是要知道你是否有一個指向結構或結構本身的指針。例如,你可以將NULL存儲在類型的變量中嗎?如果隱藏某個對象是一個指針,則必須創建一個特殊的NIL_NODE或其他值來替換NULL。如果你只是把它作爲一個指針,那麼人們可以像一個對待它。

另一個重要的好處是可以將實際的結構定義置於某處,即在.c文件中而不是頭文件中。你可以在頭文件中只放入typedef,同時保持結構本身對API用戶不透明。這要求人們只使用您提供的導出方法來操縱結構。這也意味着如果您更改結構字段,則不必重建世界。

採取這種方式的另一個原因是,有時您確實需要一個可以複製的結構,而您仍然想要typedef。拿一個東西一樣GdkPoint:

typedef struct { 
    int x, y; 
    } GdkPoint; 

這是非常有用的,允許直接結構訪問,如:

GdkPoint point = { 10, 10 }; 
GdkPoint copy = point; 
do_stuff_with_point(&copy); 

但是,如果你的約定是「GdkPoint」的typedef將是一個指針,你」將不得不不一致。

如果您可以告訴指針是什麼,什麼不指定,那麼代碼就更清晰了,如果您沒有在頭文件中放置結構定義,代碼會更好地封裝(對於代表抽象,不透明數據類型的結構也許是最常見的一種)。

爲C數據類型我的默認模板是這樣的標題:

typedef struct MyType MyType; 
MyType* my_type_new(void); 
void my_type_unref(MyType *t); 
void my_type_ref(MyType *t); 

然後在.c文件的實際「結構的MyType」,用新的UNREF一起,任何類型上的操作。

例外情況是類型如點,矩形,顏色,它是「普通的舊數據」和直接字段訪問是理想的;如果你不需要refcounting,另一個變種是有一個my_type_free()而不是_unref()。

無論如何,這是一種風格,基本上是GLib風格,它被廣泛使用,並且被認爲運作良好。

+2

我完全同意。使用'typedef'來隱藏一個類型是一個指針還是一個結構(除非你爲庫接口使用不透明指針)通常不是一個好主意。說實話,我通常更喜歡調用'struct'作爲'struct'並且完全避免使用'typedef',但是如果你打算'typedef'的東西,就把它變成結構而不是指針。 – bta 2011-02-24 01:25:13

+0

glib樣式將使用CamelCase作爲一個struct typedef,而使用小寫來作爲基本類型typedef,這樣就可以在保持事物清晰的情況下,不需要鍵入「struct」。也保留了不在標題中的不透明結構的能力 – 2011-02-24 15:45:34

0

考慮使用這兩種:

typedef struct list_node Node; 
typedef Node* ListHead; 
1

我喜歡的第一個樣式,所以很清楚哪些類型的對象,和類型的指針。但我發現C指針容易理解/解釋,顯然很多人不知道。所以如果你認爲大部分閱讀你的代碼庫的人都不會理解指針,那麼在任何地方都可以使用typedef STRUCT_FOO *PSTRUCT_FOO,就像Win32 API一樣。

0

只要標識符清楚地表明它是一個指針,那麼沒有任何傷害(我個人更喜歡後綴ala _Pointer或_Ptr,但適合任何項目)。這就是說,對於純C代碼來說,避免明確的*沒有實際的好處。對於混合的C/C++環境或純粹的C++,我經常看到使用typedef指向合理化/合理化的指針,重新促進了在智能指針類型之間的轉換,使用和切換。這可能有一些事實,但我從來沒有發現自己想要採用這種做法。

0

typedef int * ptr_int; ptr_int x,y,z;

程序員可能會感到困惑,所有三個x,y,z都是int *類型,即 指向int的指針。 但是在現實中,只有x是int *類型y和z是簡單的int。

因爲ptr_int x,y,z;等於int * x,y,z; 不是int * x,* y,* z;

so, typedef也會在程序員的腦海中造成混淆,並可能導致錯誤和錯誤。