C语言不要重复包含.h头文件和.c文件

知识点滴 - 关于头文件的重复包含问题 对于函数声明来说,如果一个编译单元里出现多次相同的声明没有问题,但如果是一个编译单元里对同一个对象(变量)或类型有多个定义,或者是同一个作用域里有重复定义,比如全局空间有重复定义,就会编译报错。重复包含一个头文件,可能会导致编译错误,就算头文件中都是可以重复出现的声明之类的内容,多次包含的话,也会增加预处理器或编译器的工作量,增加软件构建的时间。在一个源文件中包含此头文件my_include.h时,会检查此宏定义是否定义,如果是第一次包含,没有定义,则下一步定义这个宏,并将后面的内容包含进来。 阅读详情

1.不要重复包含头文件



--以上出自《C语言程序设计:现代方法(第2版)》

f3.h

//#ifndef AE_OK
#define AE_OK 0
typedef int        ngx_int_t;
//#endif

f2.h

#include "f3.h"

f1.h

#include "f3.h"

test.c

#include <stdio.h>

#include "f1.h"
#include "f2.h"

int main(){
	ngx_int_t a1=1;
	printf("%d",AE_OK);
	printf("%d",a1);
	return 0;
}

编译不过去:

导出预编译文件:

...以上省略
# 2 "test.c" 2

# 1 "f1.h" 1
# 1 "f3.h" 1


typedef int ngx_int_t;
# 1 "f1.h" 2
# 4 "test.c" 2
# 1 "f2.h" 1
# 1 "f3.h" 1


typedef int ngx_int_t;
# 1 "f2.h" 2
# 5 "test.c" 2

int main(){
 ngx_int_t a1=1;
 printf("%d",0);
 printf("%d",a1);
 return 0;
}

如果我们在f3.h中增加#ifndef就不会出问题了,直接导出预编译文件:

# 2 "test.c" 2

# 1 "f1.h" 1
# 1 "f3.h" 1


typedef int ngx_int_t;
# 1 "f1.h" 2
# 4 "test.c" 2
# 1 "f2.h" 1
# 5 "test.c" 2

int main(){
 ngx_int_t a1=1;
 printf("%d",0);
 printf("%d",a1);
 return 0;
}


2. .c文件编译注意不要重复引入

这个是我从redis源码中抽取其事件库的编译

在redis源码的ae.c文件:

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <poll.h>
#include <string.h>
#include <time.h>
#include <errno.h>

#include "ae.h"
#include "zmalloc.h"
#include "config.h"

/* Include the best multiplexing layer supported by this system.
 * The following should be ordered by performances, descending. */
#ifdef HAVE_EVPORT
#include "ae_evport.c"
#else
    #ifdef HAVE_EPOLL
    #include "ae_epoll.c"
    #else
        #ifdef HAVE_KQUEUE
        #include "ae_kqueue.c"
        #else
        #include "ae_select.c"
        #endif
    #endif
#endif

aeEventLoop *aeCreateEventLoop(int setsize) {
    aeEventLoop *eventLoop;
    int i;

    if ((eventLoop = zmalloc(sizeof(*eventLoop))) == NULL) goto err;
    eventLoop->events = zmalloc(sizeof(aeFileEvent)*setsize);
    eventLoop->fired = zmalloc(sizeof(aeFiredEvent)*setsize);
    if (eventLoop->events == NULL || eventLoop->fired == NULL) goto err;
    eventLoop->setsize = setsize;
    eventLoop->lastTime = time(NULL);
    eventLoop->timeEventHead = NULL;
    eventLoop->timeEventNextId = 0;
    eventLoop->stop = 0;
    eventLoop->maxfd = -1;
    eventLoop->beforesleep = NULL;
    if (aeApiCreate(eventLoop) == -1) goto err;
    /* Events with mask == AE_NONE are not set. So let's initialize the
     * vector with it. */
    for (i = 0; i < setsize; i++)
        eventLoop->events[i].mask = AE_NONE;
    return eventLoop;

err:
    if (eventLoop) {
        zfree(eventLoop->events);
        zfree(eventLoop->fired);
        zfree(eventLoop);
    }
    return NULL;
}

HAVE_EPOLL是前面定义的:

/* Test for polling API */
#ifdef __linux__
#define HAVE_EPOLL 1
#endif

在ae_epoll.c中的aeApiCreate函数

#include <sys/epoll.h>

typedef struct aeApiState {
    int epfd;
    struct epoll_event *events;
} aeApiState;

static int aeApiCreate(aeEventLoop *eventLoop) {
    aeApiState *state = zmalloc(sizeof(aeApiState));

    if (!state) return -1;
    state->events = zmalloc(sizeof(struct epoll_event)*eventLoop->setsize);
    if (!state->events) {
        zfree(state);
        return -1;
    }
    state->epfd = epoll_create(1024); /* 1024 is just an hint for the kernel */
    if (state->epfd == -1) {
        zfree(state->events);
        zfree(state);
        return -1;
    }
    eventLoop->apidata = state;
    return 0;
}

我想抽取出redis的事件库

一开始不知道include的.c文件编译的时候不需要重复引入,不然编译报错:

ae_epoll.c不用被引入,因为在ae.c已经引入了。


成功编译:

生成了redis文件。


2. .h文件编译注意不要重复引入

报错anet.h:47: 错误:expected declaration specifiers or ‘...’ before ‘size_t’


原因是anet.h头文件重复引用,去掉anet.h,重新编译就可以了:

原因分析:

b.h中#include "../../a.h" 而a.h中的函数声明中用到了b.h中的结构体或者typedef,那么就会出现在包含a.h的时候b.h中的结构体或者typedef还没有声明,从而陷入错误。

头文件重复包含和变量重复定义 在c或c++中,头文件重复包含问题是程序员必须避免的问题,也是很多新手容易犯错的问题。 为什么要避免头文件重复包含呢?        1.我们知道在编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其中一项工作便是将你源程序中#include的头文件完整的展开,如果你有意或无意的多次包含相同的头文件,会导致编译器在后面的编译步骤多次编译该头文件,工程代码量小还好,工程量一大会使整个项 阅读详情

相关推荐

C语言:如何避免头文件重复包含带来的编译和链接问题

防止头文件重复包含是头文件设计的基本要求,开发者必须为每一个头文件添加包含守卫或 #pragma once。// ❌ 错误做法(多次包含导致重定义)// ✅ 正确做法(声明+extern)// .h 中声明// .cpp 中定义。

qq_39748622的博客 1134

expected specifier-qualifier-list before 'size_t'

包含sg.h,编译的时候报错:sg.h:39: error: expected specifier-qualifier-list before 'size_t' 原来是没有把fcntl.h放在它的前面。 对于具有依赖关系的头文件,编译的时候要注意包含顺序。 另外,对于这种与数据类型有关的错误,一般不能修改头文件本身,而应该考虑使用其他方法。

ynt的专栏 3814

C 语言中防止头文件重复包含的机制

例如,假设有一个函数声明在头文件中,并且该头文件在多个源文件中都被包含。如果没有防止重复包含的机制,就会出现重复定义错误。void foo();// 函数声明如果没有防止重复包含,编译器会认为foo被多次定义,导致链接错误。使用#ifndef#define和#endif:这种方法是标准的 C 语言做法,可以有效避免头文件重复包含,广泛适用于不同的编译器和平台。使用:这种方法语法简洁,适用于大多数现代编译器,但它是编译器特有的扩展,可能不兼容某些旧版编译器。

m0_62599305的博客 1268

ubuntu下编译时遇到的错误及解决方式

1、错误展示: hangma@ubuntu:~/test/test/protest/stack_test$ gcc  -c my_stack.c -o my_stack.o In file included from /usr/include/stdio.h:34:0,                  from my_stack.c:2: /usr/lib/gcc/i686-linux-gnu...

weixin_33928467的博客 1366

C 语言编程 — 头文件

目录 文章目录目录前文列表头文件只引用一次头文件有条件引用global.h 前文列表 《程序编译流程与 GCC 编译器》 《C 语言编程 — 基本语法》 《C 语言编程 — 基本数据类型》 《C 语言编程 — 变量与常量》 《C 语言编程 — 运算符》 《C 语言编程 — 逻辑控制语句》 《C 语言编程 — 函数》 《C 语言编程 — 高级数据类型 — 指针》 《C 语言编程 — 高级数据类型 —...

烟云的计算 5347

c语言stack.h头文件 栈

c 语言 数据结构用的栈的头文件,可以让你直接引用,方便快捷

【C】.h头文件的重复包含问题

.h头文件存在的意义就是封装,可以方便多个.c源文件使用,但要防止.h头文件被同一个.c源文件多次包含。 例如, io.h文件 1 #ifndef _IO_H_ 2 #define _IO_H_ 3 #define HOLENUM 15 4 int HoleTemp; 5 void Get_Temp(unsigned char HoleID); 6 #endif ...

weixin_34235105的博客 263

TESSY创建单元测试或集成测试工程

我们以tessy5.1为例,给大家展示单元测试和集成测试工程的创建过程。

空气中的告白专栏 1686

Unix/Linux编程之size_t、ssize_t

对于赶时间的朋友,只看第一段就好了。    首先,我非常肯定以及确定的告诉你ssize_t是有符号整型,在32位机器上等同与int,在64位机器上等同与long int,有没有注意到,它和long数据类型有啥区别?其实就是一样的。size_t 就是无符号型的ssize_t,也就是unsigned long/ unsigned int (在32位下),不同的编译器或系统可能会有区别,主要是因为在3

王文松的博客 1万+

Outlook邮件备份全攻略:从导出到导入的完整流程(附常见问题解决)

本文提供了一份详尽的Outlook邮件备份全攻略,涵盖从导出到导入的完整流程。重点解析了经典桌面版Outlook的.pst文件备份方法、进阶的智能筛选备份策略,以及如何通过导入恢复和工具验证确保备份可用。同时,文章还介绍了构建自动化备份体系与异地容灾的最佳实践,并附有常见问题解决方案,帮助用户建立可靠的邮件数据安全防线。

weixin_29248611的博客 894

MATLAB2022b安装

图文并茂,手把手教会你怎么安装MATLAB2022b

1万+

c语言 自动包含头文件,C语言不要重复包含.h头文件和.c文件

http://blog.csdn.net/unix21/article/details/845023520121.不要重复包含头文件--以上出自《C语言程序设计:现代方法(第2版)》f3.h//#ifndefAE_OK#defineAE_OK0typedefintngx_int_t;//#endiff2.h#include"f3.h"f1.h#include"f3.h"...

weixin_33093437的博客 746

浙江大学Fast-Lab从0制作自主空中机器人公开课教程补充及部分注意事项(适用于ubuntu系统和ROS零基础)

浙江大学Fast-Lab从0制作自主空中机器人公开课纯萌新补充(适用于从没接触过ubuntu系统),记录了一些自己不会的地方以及踩过的坑

qq_39986834的博客 2986

【C语言初阶】文件结构(头文件结构,头文件作用,头文件被重复包含的问题)

头文件的作用;头文件的命名;头文件的结构;extern声明;头文件被重复包含的问题;定义文件(源文件);源文件的结构;源文件的双重保护;static为源文件提供安全保证;如何将源文件编译成静态库文件?(环境VS2013)

52Herzt的博客 1万+

硅电容的工艺结构原理及选型参数总结

硅电容,也称为硅质电容或硅二极管电容,是一种特殊的电容器。它利用硅二极管的结构来实现电容的功能。本文对硅电容的工作原理,结构特点,选型参数及设计注意事项进行总结。

fydar的博客 2332

基于Blender软件对Matterport3D数据集场景可视化

使用Blender软件对 Matterport3D 中的室内场景进行可视化。

qq_44100524的博客 290

C语言中头文件包含的处理原则

很多事不深入以为自己懂了,但真正用到项目上,才发现了问题。曾以为自己写C语言已经轻车熟路了,特别是对软件文件的工程管理上,因为心里对自己的代码编写风格还是有自信的。(毕竟刚毕业时老大对我最初的训练就是编码格式的规范化处理) 曾以为,一个.c文件对应一个.h文件,.c文件只包含它自身的.h文件就好,若.c文件中用到其他文件中的内容,则.h文件把用到的头文件包含进来就...

fengcq126的专栏 9109

第150篇 激光雷达点云分割——地面分离、聚类分析和物体提取

本文介绍了点云分割的三种经典几何方法:RANSAC地面分离、欧式聚类和区域生长。RANSAC通过随机采样拟合平面实现地面分割,欧式聚类基于空间距离进行物体分割,区域生长则结合法线信息提升分割精度。文章对比了各种方法的优缺点,提供了参数选择建议,并指出实际项目中常组合使用这些方法。最后给出了面试应答技巧,强调几何方法速度快、可解释性强等优势,适合大多数机器人项目的实时需求。

郑伟强dev的专栏 192

【C语言】头文件重复包含问题的解决方式

- 头文件重复包含问题的解决方式包括include guards(ifndef)、_Pragma("once")和#pragma once等,本文对各种方式做了简要的总结。

一介草民,只为生活。 2694

Altera FPGA与高速ADS4249和DAC3482的LVDS接口设计

引言:本文以TI的ADS4249(ADC)和DAC3482(DAC)之间的接口为例,介绍Altera FPGA与ADC/DAC之间的DDR LVDS接口设计以及时序约束详细设计。本文介绍的实例可方便扩展到具有类似接口格式的其他高速数据转换器设计。

FPGA_Designer 1902

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

防止C语言头文件被重复包含

文章目录方法一:使用宏保护防止C语言头文件被重复包含 (很常用)方法二: #pragma once(在头文件的最开始加入) ( 比较常用) 参考链接: https://blog.csdn.net/m0_37624078/article/details/81911808 方法一:使用宏保护防止C语言头文件被重复包含 (很常用) 当1个C语言程序由 多个 源程序文件 组成时,由于每个 源程序文件 都有 #include <…> #include “…h”, 最终它们可能形成交叉 包含 和 重复包

博雅勇士的博客 9200

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

779-如何防止C语言头文件被重复包含

如何防止C语言头文件被重复包含? 一般情况下,我们都是把函数声明、类定义、模板定义等写到一个头文件里,需要时将相应的头文件用#include包含到源文件(*.c文件)里来。但头文件中又允许包含其它的头文件,这样就难免发生某个头文件被重复地包含。 我们可以使用编译预处理命令避免这种情况的发生。 方法1:使用#ifndef 例如,你想确保头文件max.h不会被重复包含,则你可以采取如下的形式: 第一条预处理命令的意思:如果MAXMIN_H不为真,说明此文件没被包含过,此命令后面的源代码有效(相当于:‘如果大门

LINZEYU666的博客 5354

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

怎样防止头文件被重复包含?(两种方式)以及它的影响

一、头文件被重复包含 #include文件的一 个不利之处在于一个头文件可能会被多次包含,为了说明这种错误,考虑下面的代码: #include "x.h" #include "x.h" 显然,这里文件x.h被包含了两次,没有人会故意编写这样的代码。但是下面的代码: #include "a.h" #include "b.h" 看上去没什么问题。如果a.h和b.h

yx20130919的博客 2万+

【C语言】头文件

所以学习过C语言的朋友都熟悉这样一段代码: 那么,你真的了解 吗? 到底是什么呢? 和 这两种写法皆可行吗?为什么?这二者有何区别呢?如果让你自己写一个类似头文件 的头文件,你能写出来并在大型项目中四处引用属于自己的头文件吗?这篇文章像大家详细介绍 C语言中的 头文件: 头文件是一个包含函数声明、宏定义、数据类型定义和全局变量声明的文件,通常配合 .c 源文件使用。头文件通过 指令被引入到源文件中(或其他头文件中)。头文件通常包含以下内容: 宏定义:可以在头文件中定义一些宏,用于常量表达

猫猫的小茶馆 6415

C语言如何自定义.h头文件

如何自定义引入.h头文件? 文章目录如何自定义引入.h头文件?.h头文件理解Hello World.h文件.c文件编译小结初体验编译效果图DOS命令终端编译 .h头文件理解 个人理解,仅参考 .h头文件是定义方法名称,告诉外界有这个方法, 能够通过编译器编译 .h头文件就是为了让其他文件调用这个文件里面的方法 Hello World 分别创建两个文件: 新建.c文件,例:hello.c 新建.h文件,例:hello.h .h文件 条件指示符#ifndef 的最主要目的是防止头

Smile_ping的博客 1万+

头文件重复包含

一、头文件重复包含问题分析 1) 问题重现 举例说明。假设在某个C++ 头文件 或 源文件 中,包含了A.h和B.h两个头文件: #include “A.h” #include “B.h” 事实上,在头文件B.h中也包含了头文件A的引用,即: #include"A.h" 这样在编译这个文件时,因为文件包含了 A.h 这个头文件,编译器展开这个头文件,知道了 A 这个类的定义了,接着展开B.h头文件,而在B.h头文件中也包含了A.h,在此展开A.h,于是类A就重复定义了。 以上就是头文件重复包含问题的重现过程

weixin_39303983的博客 4022
上一篇: 汇编语言调用Linux系统调用
下一篇: ATT格式汇编语言
unix21
博客等级 码龄14年 115粉丝 248原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值