2010-11-16 121 views
4
gcc 4.4.4 c89 

我在我的頭文件中有這個。foward typedef結構

port.h

struct struct_tag; 

int initialize_ports(struct_tag *port); 

在我的文件實行我有這樣的:

port.c

typedef struct struct_tag { 
    int port_id; 
} Port_t; 

而且在我driver.h文件,我有以下幾點:

#include "port.h" 
int initialize_ports(struct_tag *port) 
{ 
    port = malloc(sizeof *port); 
    /* do checking here */ 
} 

我有forwa rd聲明瞭結構,因爲我想隱藏內部元素。

不過,我讓我的initialize_ports以下錯誤頭文件:

expected ‘)’ before ‘*’ token 

我只是想知道我怎麼能向前聲明並能夠通過結構作爲參數?

非常感謝任何建議,

+0

你想隱藏內部元素,但現在你隱藏他們從你自己的代碼。 'driver.h'需要訪問'port.c'中的定義,這個定義需要放在一個更適合包含某個地方的文件中。 ('.c'文件通常包含代碼,而不僅僅是類型定義。) – 2010-11-16 11:16:54

回答

5

正如其他答案已經注意到,您的可能更改struct_tagstruct struct_tag在原型。讓你的代碼編譯的另一種方式是寫

typedef struct struct_tag struct_tag; 

代替現有struct struct_tag;(即結合了前定義的類型定義)。那麼確實允許你寫

int initialize_ports(struct_tag *port) 

沒有編譯失敗。但是,這仍然不是你想要的,因爲調用者既不能分配這種類型的局部變量,也不能分配malloc() - 因爲他們不知道大小。

其他答案建議您打開結構的定義。這通常不是正確的答案 - 因爲它會移除您嘗試創建的抽象層。要好得多具備的功能(在port.c,即瞭解內部庫),如:

struct_tag *create_port(...); 
void free_port(struct_tag *port) 

即創建和自由的結構 - 事實上對其他操作(如讀取/寫入結構)。

+0

+1表示將initialize/create移動到port.c.技術上free_port不需要*去那裏,但它是合乎邏輯的地方。 – JeremyP 2010-11-16 11:58:57

+0

謝謝:)最好有一個free_port()函數,因爲端口結構本身可能包含指向其他結構的指針,這些結構在釋放端口時也需要釋放。 – psmears 2010-11-16 12:01:35

1

你會得到你不知道「口」的大小,所有它去是向前聲明的錯誤。

總之,最好不要在這裏使用前向聲明,除非你還設置了一個常量值,這個值是struct_tag的大小......你最有可能最好是完全聲明它。

+0

圓括號只用於'sizeof'類型,所以'sizeof * port'是完全有效的(除非如你所說,大小不是'在那個地方已知)。 – 2010-11-16 11:15:20

+0

@克里斯:謝謝......我不知道!修正了我的答案:) – Goz 2010-11-16 11:16:59

7

你應該使用:

int initialize_ports(struct struct_tag *port); 
        ^^^^^^ 

此外,前置聲明給你一個不完全類型你不知道的大小。如果您需要分配struct struct_tag,則需要包含其完整定義。或者,如果你想讓它完全不透明,你可以使用一些create_struct_tag()函數。

1

sizeof操作者在編譯時評價不運行時,因此在該行:

port = malloc(sizeof *port); 

編譯器具有關於該結構的大小的信息。

解決方案包括:

  • 完全定義在頭文件的類型。
  • define initialize_ports() in port.c after該結構已完全定義。
  • have initialize_ports()在運行時調用ports.c中定義的函數來獲取Port_t的大小。

在任何情況下,你應該定義在頭文件中的驅動程序initialize_ports()。除非你的編譯器支持你使用它的inline_inline關鍵字。然而,這樣的用法會使得代碼不符合ISO C標準,因此可移植性較差,但是由於C++對關鍵字的標準支持,您可能會發現它作爲大多數包含C++編譯的C工具鏈的擴展,只要您不要使用過分嚴格的合規選項。

但是,您收到的錯誤消息是由於不同的原因。與單獨使用C struct_tag的C++不同,它不代表某種類型(如果是,則不需要使用typedef!),則必須使用struct關鍵字。