c - 包含守卫不允许我声明类型
问题描述
我遇到了这么一个有趣的问题,因为包含保护触发器,头文件中声明的类型没有声明。
我有一个描述 mutex_t 类型的 mutex file.h,它取决于在线程 file.h 中声明的 thread_t 类型,但是,thread_t 取决于 mutex_t,而 main.c 文件使用这两种类型。
问题:在编译main.c的时候,thread文件是included.h,里面包含mutex.h,但是由于thread.h已经连接,所以推出了include guard,不允许在mutex中声明thread_t类型。H
线程.h
#ifndef _THREAD_H_
#define _THREAD_H_
#include "mutex.h"
typedef struct thread
{
int thread_data;
} thread_t;
extern mutex_t* get_mutex();
#endif
互斥体.h
#ifndef _MUTEX_H_
#define _MUTEX_H_
#include "thread.h"
#include "stdint.h"
typedef struct mutex {
uint8_t lock_status; //+0
thread_t* waiting_thread_queue[1024];
} mutex_t;
extern thread_t* get_thread();
#endif
主程序
#include "stdlib.h"
#include "stddef.h"
#include "thread.h"
int main(void) {
get_thread();
get_mutex();
return 0;
}
这是我得到的错误:
emilia@emilia-pc:~/test$ gcc main.c
In file included from thread.h:4,
from main.c:3:
mutex.h:9:5: error: unknown type name ‘thread_t’
9 | thread_t* waiting_thread_queue[1024];
| ^~~~~~~~
mutex.h:12:8: error: unknown type name ‘thread_t’
12 | extern thread_t* get_thread();
| ^~~~~~~~
解决方案
您在两个标头之间存在循环依赖关系。线程头需要互斥体,反之亦然。
你这样做的方式没有意义。线程头声明了一个名为的函数get_mutex
,反之亦然,互斥头声明了一个名为的函数get_thread
。
可能,这表明标题是如此密切相关,它们应该是一个标题。
无论如何,我们可以打破循环依赖的方法是在其中一个标头中使用前向声明。
// child.h
struct parent; // incomplete "forward" declaration
struct child {
struct parent *parent;
};
// parent.h
#include "child.h"
#define MAX_CHILDREN 42
struct parent {
struct child *children[MAX_CHILDREN];
};
“转发”声明struct parent
不需要parent.h
标题。标parent.h
头选择了该声明,但它不会干扰自己的声明,因为这是允许的:
struct parent;
struct parent { ... };
请注意,这会_THREAD_H_
侵入保留的实现命名空间。保留以下划线开头的名称,后跟大写字母或另一个下划线。违反此规则实际上是未定义的行为,可能会产生任何后果。该实现可以使用诊断消息停止翻译您的程序。或者它可以预定义一个名为 的宏_THREAD_H_
,以便您自己的标头无法生成其预期的内容。
推荐阅读
- julia - 使用限制器批量下载数据
- mysql - 如何使用自定义设置在无人值守的情况下安装 MySQL?
- python - Python OpenCV--MAC 网络摄像头不关闭
- string - 在 Mac OS 上的 shell 脚本中将字符串的第一个字符从大写转换为小写的正确方法是什么?
- xcode - React Native 如何更改 iOS 包标识符?
- ubuntu-16.04 - Pygobject 构建失败
- javascript - 重新加载页面时,如何使用现有数据刷新 Google 地图标记和地图?
- php - tenants.php 路由文件指向根目录
- bash - 使用进程替换与管道有什么区别?
- vba - 我试图让这个宏包括从工作簿中的多个工作表复制数据的能力,但它只会从第一个工作表复制