不允许使用不完整的类型 c语言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不允许使用不完整的类型 c语言相关的知识,希望对你有一定的参考价值。

/* nfa.h */
#ifndef NFA_H
#define NFA_H

typedef struct Node_t* Node_t;
typedef struct Nfa_t* Nfa_t;
struct Nfa_t

int start; // start node of an NFA
int accept; // accept node of an NFA
Node_t nodes; // a list of all nodes
;

Nfa_t Nfa_new ();
void Nfa_addEdge(Nfa_t nfa, int from, int to, int c);
void Nfa_print (Nfa_t nfa);

#endif

/*file nfa.c */
#include <assert.h>
#include <stdio.h>
#include "nfa.h"
#include "new.h"

typedef struct Edge_t *Edge_t;

struct Node_t

int num;
int visited;
Edge_t edges;
Node_t next; // 不允许使用不完整的类型, 求解答.谢谢.
;

// 另外一个问题, vs中要求在代码块中所有变量的定义一定要放在代码块的开头处, 有没有办法跳过这条要求?

struct Node_t

int num;
int visited;
Edge_t edges;
struct Node_t * next; //1. 少了struct 2.少了星号,就不是指针变量了。
;
要明确一点,只能用已经定义好的类型定义变量,但指针变量在定义的时候可以不需要完整的定义。这是因为所有类型的指针都是指针,指针的基础类型都是一样的,占据的空间也是一样的,所以定义成指针类型,不管这个指针是什么类型的指针,系统都会知道分配多少的空间。

在开始的地方定义变量是C语言的要求,要想变量随时用随时定义,要用C++语法,一般把文件保存成*.cpp的扩展名,就会自动用C++编译了。
参考技术A /*file nfa.c 注意,你这是C文件,若想实现你的想法,你要写成nfa.cpp,即c++文件就可以了*/
#include <assert.h>
#include <stdio.h>
#include "nfa.h"
#include "new.h"

typedef struct Edge_t *Edge_t;

struct Node_t

int num;
int visited;
Edge_t edges;
// Node_t next; // C++编译支持这种写法,C编译不支持
struct Node_t *next ; //C必须要加上struct才可以!
;本回答被提问者采纳

typedef struct 导致“不允许指向不完整类型的指针”错误

【中文标题】typedef struct 导致“不允许指向不完整类型的指针”错误【英文标题】:typedef struct leads to "pointer to incomplete type not allowed" error 【发布时间】:2021-09-01 03:29:18 【问题描述】:

我正在使用一个在其标头 (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。即使在阅读了this 和this 之后,我仍然看不到我做错了什么......

【问题讨论】:

httpc_state_t 尚未在 .h 文件中定义,因此您无法访问其成员。这可能是不透明指针的示例指针,这意味着 libaray 故意禁止您直接使用 httpc_state_t 的成员。寻找任何可以帮助您设置timeout_ticks的辅助函数。 库的意图可能是您应该访问代码中结构的成员。假设您指的是github.com/RT-Thread/IoT_Board/blob/master/rt-thread/components/…,则httpc_state_t 类型的结构由httpc_init_connection_common 分配和初始化。这包括timeout_ticks 的值。为什么需要修改库的内部数据? @Bodo (and mediocrevegetable) 感谢您的 cmets。我想你是对的,他们不希望我更改数据。问题是,我正在下载一个“大”文件(512KB)作为测试,这需要的时间超过了超时允许的时间。我希望 http_client 会在下载仍在进行并且正在接收数据包时重置计时器。但在他们的库中,超时计数器只会减少。我找不到任何帮助函数或任何可以让我控制这种行为的东西 我注释掉了减少计数器的行(给了我一个无限超时),然后下载一直没有任何问题。但我一定是错过了什么。他们实施该机制当然是有原因的...... PS:头文件在这里:git.savannah.nongnu.org/cgit/lwip.git/tree/src/include/lwip/…,源文件在这里:git.savannah.nongnu.org/cgit/lwip.git/tree/src/apps/http/… 【参考方案1】:

在定义函数rec_fn的翻译单元中,编译器只看到以下声明

typedef struct _httpc_state httpc_state_t;

对于本语句中使用的数据成员timeout_ticks是否一无所知

req->timeout_ticks = 30;

确实在结构 struct _httpc_state 中声明,它的类型是什么。即名称 timeout_ticks 在此翻译单元中未声明。所以编译器会报错。

如果您要在翻译单元中使用结构的数据成员,那么编译器需要知道它们的声明。也就是说,您还需要包含结构定义。

如果允许,请在标题中移动结构定义,或者在定义函数的模块中复制其定义。

请注意,如果结构定义没有放在头文件中,那么原因可能是代码的作者不想让它在他的模块或库之外可用。

【讨论】:

我尝试了你的技巧(在我自己的源文件中复制 def),效果很好。我以为我会收到重复定义的错误,但我猜链接器会解决这个问题。但正如我的问题下面的 cmets 也建议的那样,我想我这样做是错误的方向。【参考方案2】:

不完整类型意味着它已声明但未定义。您需要在头文件中定义该结构并将其包含到您的 C 文件中。

【讨论】:

【参考方案3】:

错误信息措辞不当。

指向不完整类型的指针很好! 取消引用不完整类型的成员是个问题。

在发生错误时,编译器还没有“看到”该翻译单元中类型的完整定义。

它识别类型,但不知道该类型是否有成员timeout_ticks,更不用说如何生成访问它的代码了。 [比如成员相对于对象开始的位置。]

指向不完整类型的指针是减少依赖和代码耦合的有用方法。如果代码只需要传递指向类型周围的类型的指针,则可以声明(不完整)并帮助进行类型检查,但不暴露于完整定义。

【讨论】:

以上是关于不允许使用不完整的类型 c语言的主要内容,如果未能解决你的问题,请参考以下文章

不允许使用不完整的类型 c语言

c语言报错不允许使用不完整类型,让用户自定义数组大小。

用VS15编写多文件程序的时候,c语言提示不允许使用不完整的类型

C语言不允许使用不完整的类型报错是啥意思啊

c++mfc为何报错不允许指针指向不完整的类类型?

c语言中,定义数组和引用数组时,其数组的下标的数据类型分别允许是啥?