2010-08-17 43 views
0

在理論上似乎書籍sugest用C聲明ADT爲:ADT在C - 有或沒有指針?

struct some_structure; 
typedef some_structure *some_structure_t; 

而大多數代碼使用:

struct some_structure; 
typedef some_structure some_structure_t; 

我知道const不與第一種樣式的工作。這是真正的圖書館不使用第一種方法的唯一原因嗎?有沒有其他的通知或建議?

+0

所以看起來 - 感謝所有好的答案 - 第二種風格(顯式指針)更實用。非常感謝您的幫助。 – 2010-08-19 08:03:52

回答

4

您的意思是抽象數據類型?如果我從你的代碼snipsets中的語法錯誤中抽象;-),我認爲是的typedef指針類型是皺眉,因爲constvolatile的問題。

順便說一句,您的代碼的另一個問題是您選擇的名稱。 _t作爲結尾保留在POSIX中供將來使用。

+0

只因爲這個?對於ADT,「volatile」真的有用嗎? 我不知道'_t'被儲存。然而,許多庫使用這個約定。你知道任何更安全的約定(但請不要「_T」)。 – 2010-08-17 13:44:51

+0

@ dpc.ucore.info另一種方法是對類型使用大寫字母,即Some_Structure_func()函數的Some_Structure和小寫字母。 – quinmars 2010-08-17 13:55:32

+0

@ dpc.ucore.info:這是很好的做法,一個庫被許多人用來選擇一個前綴,並堅持使用它在頭文件中使用的所有符號和/或在對象中導出。例如,對於POSIX線程,使用'pthread_'作爲符號,'PTHREAD_'作爲宏。 (他們再次也有'_t',因爲它是POSIX。) – 2010-08-17 15:23:53

1

我用

typedef struct some_s *some_t; 

和地方事務我要麼使用const struct some_s*typedef const struct some_s *const_some_t,但我想這是個人喜好的問題。

+0

另一種類型的const的聲明是個好主意,謝謝。 – 2010-08-17 13:45:40

+0

你是否以某種奇特的方式處理鑄造?承諾不改變對象的函數應該接受'some_t'來代替'const_some_t'。 – 2010-08-17 14:06:33

+2

@ dpc.ucore.info:你不需要。只需將some_t傳遞給sig爲const_some_t的函數,不會發出警告(至少它不會在icc,gcc和pcc上)。 – hroptatyr 2010-08-17 14:18:46

0

我以前用第一種方式去,但是我發現我對於訪問結構成員所需的間接尋址級別感到困惑,於是我開始向指針類型添加後綴,例如,

typedef struct AStruct *AStructRef; 

但後來我意識到我正在有效地重新創建*運算符以阻止我被隱藏*運算符所迷惑。所以,現在我採用第二種風格。

2

抽象數據類型對於像「對象」這樣的東西有效執行操作很有用。

如果可以,在C中,完全避免使用「typedef」關鍵字。它掩蓋了真正發生的事情。作爲初學者,我建議你在任何你想使用typedef的地方都明確輸入struct AStruct

從那裏你可以通過聲明一個函數,該函數將一個指向「抽象數據類型」(或對象,我喜歡思考)的指針作爲第一個參數,對你的「抽象數據類型」執行一個「動作」然後是正常參數。

例如

int some_func(struct AStruct *pObject, int param1, int param2) { 
    if ((param1 < 0) || (param2 < 0)) 
    return(0); 
    pObject->val = param1 + param2; 
    return(1); 
} 

然後使用:

#include <stdio.h> 
int main(void) { 
    struct AStruct myObject; 

    if (some_func(&myObject, 10, 12)) { 
    printf("Processed: %d\n", myObject.val); 
    } else { 
    printf("Failed\n"); 
    } 
    return(0); 
} 
+0

+1第二個建議是爲了避免爲了方便而避免'typedef'結構。在'name_t'上面寫'struct name'只是瑣碎的工作。 OP注意到,保留數據類型爲'struct'的清晰指示可以幫助防止'const'出現問題。被迫寫'struct name *'而不是'name_ptr_t'也避免了JeremyP在他的回答中提到的一些間接混淆(指針顯然明顯地被聲明爲這樣)。 – bta 2010-08-17 16:21:35

2

這取決於什麼其他人的代碼將與這些類型做。由於磁帶庫的用戶,如果我認爲some_structure_t是一個結構,而不是一個指向一個結構,我可能會做這樣的事情:

some_structure_t *p; 

p = malloc(sizeof *p); 
memcpy(p, &another_p, sizeof *p); 

也許這是我的背景,作爲一個嵌入式的程序員,但我想在我使用它的代碼中瞭解有關some_structure_t的更多信息。即使它是一個真正的抽象類型,並且它只被用作最終用戶代碼中的參數或返回值,但您仍然必須在支持該類型的庫中處理它。如果我看到了下面的代碼,我會做恍然大悟:

some_structure_t some_function(some_structure_t foo) 
{ 
    some_structure_t retval; 

    retval = malloc(sizeof *retval); // assigning pointer to struct? 
    retval->member = foo->member;  // using -> instead of .? 

    return retval;      // returning potentially large structure on stack? 
} 

也許這是最大的一個 - 從一個some_structure_t複製到另一個。如果是intfloatstruct,則編寫foo = bar將進行復制。如果some_structure_t被定義爲指向結構體的指針,則foobar指向同一個對象。也許這就是你想要的,但對我來說似乎有風險。

我不知道MISRA有沒有關於指針的typedefs的說法。

+0

準確地說 - 在C中被認爲是不好的風格來隱藏類型是指針的事實,因爲類型的用戶無論如何都需要知道這一點。因此標準庫提供了'FILE *'。 – caf 2010-08-18 03:06:22