簡體   English   中英

typedef 結構導致“不允許不完整類型的指針”錯誤

[英]typedef struct leads to “pointer to incomplete type not allowed” error

我使用的庫在其標頭 ( http_client.h ) 中包含以下聲明:

typedef struct _httpc_state httpc_state_t;

該庫在實現中定義了結構 ( http_client.c )

typedef struct _httpc_state
{
  struct altcp_pcb* pcb;
  ip_addr_t remote_addr;
  u16_t remote_port;
  int timeout_ticks;
  struct pbuf *request;
  struct pbuf *rx_hdrs;
  u16_t rx_http_version;
  u16_t rx_status;
  altcp_recv_fn recv_fn;
  const httpc_connection_t *conn_settings;
  void* callback_arg;
  u32_t rx_content_len;
  u32_t hdr_content_len;
  httpc_parse_state_t parse_state;
#if HTTPC_DEBUG_REQUEST
  char* server_name;
  char* uri;
#endif
} httpc_state_t;

在同一個 C 文件中,它實現了以下使用結構體的函數:

/** http client tcp poll callback */
static err_t
httpc_tcp_poll(void *arg, struct altcp_pcb *pcb)
{
  /* implement timeout */
  httpc_state_t* req = (httpc_state_t*)arg; // Here the void pointer is casted to httpc_state_t
  LWIP_UNUSED_ARG(pcb);
  if (req != NULL) {
    if (req->timeout_ticks) { // Here the concrete type is used. Works. No problems.
      req->timeout_ticks--;
    }
    if (!req->timeout_ticks) {
      return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK);
    }
  }
  return ERR_OK;
}

我有一個使用這個庫的 C++ 文件,當然包括所需的頭文件 ( http_client.h )。

extern "C"
{
    #include "FreeRTOS.h"
    #include "task.h"
    #include "semphr.h"

    #include "lwip/tcpip.h"
    #include "lwip/apps/http_client.h"  // Here I include their http_client.h file

    #include "projdefs.h"
}

在我的下一個函數中,我需要完全按照他們的實現做。 我需要對httpc_state_t 我實現了他們的回調函數如下:

err_t rec_fn(void *arg, struct altcp_pcb *conn, struct pbuf *p, err_t err)
{
    if (p)
    {
        httpc_state_t* req = (httpc_state_t*)arg; // Compiler sees no problems in casting to my desired type....
        req->timeout_ticks = 30; // COMPILE ERROR, pointer to incomplete class type _httpc_state is not allowed 
    }
}

為什么我會收到那個編譯錯誤?! 包括頭文件。 頭文件聲明了 typedef。 即使在閱讀了這個這個之后,我仍然不明白我做錯了什么......

不完整類型意味着它已聲明但未定義。 您需要在頭文件中定義該結構並將其包含在您的 C 文件中。

在定義函數rec_fn的翻譯單元中,編譯器只能看到以下聲明

typedef struct _httpc_state httpc_state_t;

它對這條語句中使用的數據成員timeout_ticks是否一無所知

req->timeout_ticks = 30;

確實在結構struct _httpc_state聲明了它的類型。 即名稱timeout_ticks在此翻譯單元中未聲明。 所以編譯器會報錯。

如果您打算在翻譯單元中使用結構的數據成員,那么編譯器需要知道它們的聲明。 也就是說,您還需要包含結構定義。

如果允許,請在標題中移動結構定義,或者在定義函數的模塊中復制其定義。

請注意,如果結構定義未放置在標題中,則原因可能是代碼作者不想使其在其模塊或庫之外可用。

錯誤消息措辭不當。

指向不完整類型的指針很好! 取消引用不完整類型的成員是問題所在。

在發生錯誤時,編譯器還沒有“看到”該翻譯單元中類型的完整定義。

它識別類型,但不知道該類型是否有成員timeout_ticks更不用說如何生成訪問它的代碼了。 [例如成員相對於對象開始的位置。]

指向不完整類型的指針是減少依賴性和代碼耦合的有用方法。 如果代碼只需要傳遞指向類型的指針,則可以聲明(不完整)類型並幫助進行類型檢查,但不會暴露給完整定義。

暫無
暫無

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

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