結構體的定義位置不正確導致的錯誤

今天遇到一個結構體數組的定義錯誤,MDK編譯器報錯爲:
error: expression must be a pointer to a complete object type
本以爲是函數形參爲指針,調的是結構體變量名而出錯,以前遇到過這種調用錯誤。但是檢查後發現並沒有調用問題。結構體數組定義如下:

"func.c"中:
struct msg_param{
uint16_t number;
uint16_t data;
};
const struct msg_param msg_group[]{
{1,0x0001},
{2,0x00F1},
{3,0x00FF},
};

"message.c"中:
extern const struct msg_param msg_group[];/*結構體數組聲名*/
void msg_write(uint16_t nbr, uint16_t data); /*函數聲名*/

msg_write(msg_group[1].number, msg_group[1].data); /*按該結構體寫數據*/

然後編譯就出現了:
error: expression must be a pointer to a complete object type
結過反覆檢查,認爲問題出在結構體數組聲名上。在message.c中聲名了在其他文件中定義的結構體數組,而沒有放在.h文件中,這樣是不是有問題?仔細想想,沒問題呀,在.h中包含進來以後,跟直接在.c中聲名應該是一樣的。
再仔細檢查,發現是不是因爲struct msg_param沒有被聲名呢?於是在message.c中增加聲名結構體語句,成爲下面這樣:
extern const struct msg_param;/*聲名結構體*/
extern const struct msg_param msg_group[];/*結構體數組聲名*/
void msg_write(uint16_t nbr, uint16_t data); /*函數聲名*/
msg_write(msg_group[1].number, msg_group[1].data); /*按該結構體寫數據*/

結果還是報錯。然後忽然想起來,結構體定義的是一種類型,怎麼可以被“聲名”呢!
只有變量和函數才能被“聲名”呀!
於是把message.c的結構體聲名變成結構體定義,成爲這樣:
struct msg_param{
uint16_t number;
uint16_t data;
};   /*將func.c中的結構體定義複製到這裏*/
extern const struct msg_param msg_group[];/*結構體數組聲名*/
void msg_write(uint16_t nbr, uint16_t data); /*函數聲名*/
msg_write(msg_group[1].number, msg_group[1].data); /*按該結構體寫數據*/

編譯通過!
至此又對結構體定義有了進一步的理解,結構體定義的一種類型!
typedef struct xx{;}XXX;之類的,又是把結構體類型定義成一個更省事的結構體類型!
雖然之前在教材和文獻上屢次看到這句話,但過久了,還是沒有實際的理解。
因爲通常寫程序都是按“規矩”把結構體定義在.h文件中的,這樣肯定就被多個.c包含了,不會出現找不到結構體類型的情況。
這次定義在.c中,結果就出了問題。看來前人在C語言編程中創造了.h文件,並且一再強調結構體定義要放在.h中,還是很有他們的道理的,玄機頗深啊。
 
 
 
發佈了40 篇原創文章 · 獲贊 38 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章