簡體   English   中英

如何修復由C中struct內struct引起的不完整類型錯誤?

[英]How to fix incomplete type error caused by struct inside struct in C?

我正在開發一個使用我自己創建的多個庫的項目。 其中一些庫相互依賴,為了避免循環依賴問題,我使用了前向聲明頭方法,該方法包括為前向聲明創建一個單獨的文件,如本文的一個答案中所述: 解決由於類之間的循環依賴導致的構建錯誤

在某些標頭中,我創建了包含指向其他標頭中結構的指針的結構,並且沒有問題。 但是,現在我需要聲明一些包含結構而不是結構指針的結構。 例如,這些是我在名為 Capa2.h 的文件中所做的聲明。

#include "Capa2_fwd.h"
#include "Net_fwd.h"
#include "Grafico.h"

#define TAM_MAX_PAYLOAD 248

#pragma pack(push, 1)

struct cab_arp_ {
    short tipo_hw;
    short tipo_proto;
    char lon_dir_hw;
    char lon_dir_proto;
    short cod_op;
    dir_mac_t mac_origen;
    unsigned int ip_origen;
    dir_mac_t mac_destino;
    unsigned int ip_destino;
};

struct cab_ethernet_ {
    dir_mac_t mac_destino;
    dir_mac_t mac_origen;
    short type;
    char payload[TAM_MAX_PAYLOAD];
    unsigned int FCS;
};

#pragma pack(pop)

struct entrada_arp_ {
    dir_ip_t dir_ip;
    dir_mac_t dir_mac;  
    char nombre_if[16]; 
};

struct tabla_arp_ {
    Lista_t *entradas_arp;
};

這些是 Capa2_fwd.h 中的前向聲明。

typedef struct cab_arp_ cab_arp_t;
typedef struct cab_ethernet_ cab_ethernet_t;
typedef struct entrada_arp_ entrada_arp_t;
typedef struct tabla_arp_ tabla_arp_t;

我收到這些錯誤。

In file included from ./inc/Net.h:10, from ./inc/Grafico.h:7, from prueba.c:2:

./inc/Capa2.h:18:12: error: field ‘mac_origen’ has incomplete type

18 |  dir_mac_t mac_origen;

./inc/Capa2.h:20:12: error: field ‘mac_destino’ has incomplete type

20 |  dir_mac_t mac_destino;

./inc/Capa2.h:25:12: error: field ‘mac_destino’ has incomplete type

25 |  dir_mac_t mac_destino;

./inc/Capa2.h:26:12: error: field ‘mac_origen’ has incomplete type

26 |  dir_mac_t mac_origen;
  
./inc/Capa2.h:35:11: error: field ‘dir_ip’ has incomplete type

35 |  dir_ip_t dir_ip;

./inc/Capa2.h:36:12: error: field ‘dir_mac’ has incomplete type

36 |  dir_mac_t dir_mac;

導致錯誤的類型在 Net_fwd.h 中聲明

typedef struct dir_ip_ dir_ip_t;
typedef struct dir_mac_ dir_mac_t;
typedef struct prop_nodo_ prop_nodo_t;
typedef struct prop_intf_ prop_intf_t;

並且結構在 Net.h 中聲明

#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Grafico.h"
#include "Net_fwd.h"
#include "Capa2.h"
#define TAM_DIR_MAC 6
#define TAM_DIR_IP 16

#pragma pack(push, 1)

typedef struct dir_ip_ {
    char dir_ip[TAM_DIR_IP];
} dir_ip_t;    
typedef struct dir_mac_ {
    char dir_mac[TAM_DIR_MAC];
} dir_mac_t;

#pragma pack (pop)

struct prop_nodo_ {
    bool tiene_dir_loopback;
    dir_ip_t dir_loopback;      
};    
struct prop_intf_ {
    bool tiene_dir_ip;
    dir_ip_t dir_ip;
    dir_mac_t dir_mac;
    char mascara;
};

我知道如果我想將結構放入結構中,前向聲明是不夠的,但我不知道如何解決這個問題。

當您聲明一個變量/字段是指向結構類型的指針時,編譯器不需要知道定義,直到您取消引用代碼中的指針,因為變量/字段的大小為 8 個字節(在 64 位上)建築學)。 當您將變量/字段聲明為結構體類型時,編譯器必須知道結構體的大小是多少才能分配足夠的內存。 重命名結構的 typedef 可以向前,因為不需要大小。 但是如果你想用結構化類型聲明字段,那么結構聲明必須按拓撲順序出現。 所以編譯器必須在 Capa2.h 之前看到 Net.h。

更新

因此,根據您的評論,唯一的方法是更改​​您包含所有內容的方式。 以下場景是否符合您的需求?

首先,忘記前向聲明,然后:

卡帕2.h

#ifndef _INC_CAPA2_H
#define _INC_CAPA2_H

#include "Net.h"

#define TAM_MAX_PAYLOAD 248

#pragma pack(push, 1)

struct cab_arp_ {
    short tipo_hw;
    short tipo_proto;
    char lon_dir_hw;
    char lon_dir_proto;
    short cod_op;
    dir_mac_t mac_origen;
    unsigned int ip_origen;
    dir_mac_t mac_destino;
    unsigned int ip_destino;
};

struct cab_ethernet_ {
    dir_mac_t mac_destino;
    dir_mac_t mac_origen;
    short type;
    char payload[TAM_MAX_PAYLOAD];
    unsigned int FCS;
};

#pragma pack(pop)

struct entrada_arp_ {
    dir_ip_t dir_ip;
    dir_mac_t dir_mac;  
    char nombre_if[16]; 
};

#endif

凈小時

#ifndef _INC_NET_H
#define _INC_NET_H

#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "Capa2.h"

#define TAM_DIR_MAC 6
#define TAM_DIR_IP 16

#pragma pack(push, 1)

typedef struct dir_ip_ {
    char dir_ip[TAM_DIR_IP];
} dir_ip_t;    
typedef struct dir_mac_ {
    char dir_mac[TAM_DIR_MAC];
} dir_mac_t;

#pragma pack (pop)

struct prop_nodo_ {
    bool tiene_dir_loopback;
    dir_ip_t dir_loopback;      
};    
struct prop_intf_ {
    bool tiene_dir_ip;
    dir_ip_t dir_ip;
    dir_mac_t dir_mac;
    char mascara;
};

#endif

主程序

#include "Capa2.h"
#include "Net.h"


int _tmain(int argc, _TCHAR* argv[])
{
    cab_arp_ x;
    prop_intf_ y;
    return 0;
}

這對我來說是成功編譯的,除非你的項目有一些你沒有提到的其他復雜性,否則對你的也應該沒問題。


舊答案

如果不知道所有標題的內容,就很難就此提出建議。 我想到的第一件事是使用頭球后衛。

將每個頭文件的內容包裝在#ifndef指令中,如下所示。 確保為每個標頭使用不同的名稱( _INC_CAPA2_FWD_INC_NET_FWD等):

#ifndef _INC_CAPA2_FWD
#define _INC_CAPA2_FWD

// header content goes here

#endif // _INC_CAPA2_FWD

這樣,您可能也不需要進行前向聲明。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM