C语言头文件到底是什么?

在C语言学习的时候总是会引入这样的语句#include ,书上解释说把stdio.h这个文件的全部内容直接插入到这个位置,然后再经过C语言的编译器编译运行。这么看来隐含的意思好像是.h头文件好想并不直接参与编译。

围绕这个话题引出了下面这几个问题。

一,.h头文件会参与编译吗?

不妨来做个实验

这个是head.h文件的内容

#include

int main() {

printf("Hello World!");

return 0;

}

这个是ori.c文件的内容

#include "head.h"

编译执行gcc ori.c -o ori

发现输出的是

>> .\ori.exe

>> hello world!

.c文件中并没有引入任何其他的文件,除了我们自己定义的head.h头文件,而在这个头文件中,我们引入了stdio.h头文件,并且我们在head.h里面定义的main函数被执行了,由此证明了include xxx.h是直接原封不同的插入到引用这个头文件的.c文件中的。

但是会参与编译吗?

为此设计下面这个实验:

开一个项目,在.h头文件里面定义main函数,

不引用这个头文件直接编译整个项目,然后执行,

如果没有输出main函数内部的内容,那么表明如果不加引用,.h文件不参与编译。

否则就参与编译。

这个是head.h文件内容

#include

int main() {

printf("Hello World! I am head.h");

return 0;

}

这个是ori.c文件的内容

// nothing

编译执行gcc ori.c -o ori

发现输出的是

C:/Program Files/MinGW/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/../../../../x86_64-w64-mingw32/lib/../lib/libmingw32.a(lib64

_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x2e): undefined reference to `WinMain'

collect2.exe: error: ld returned 1 exit status

报错了,undefined reference to WinMain未定义WinMain

这时候我们在ori.c内部定义这样的一个函数

#include

int WinMain() {

printf("Hello world! I am WinMain!");

return 0;

}

再次编译运行gcc ori.c -o ori

运行.\ori.exe

>> .\ori.exe

>> Hello world! I am WinMain!

发现正常输出了WinMain函数内部的内容,这也告诉我们WinMain函数同样可以作为程序的入口。

经过实验发现,的的确确.h绝对不是直接参与编译的,而是通过.c文件中#include "xxx.h"语句手动插入的。

这其实间接解答了在.h头文件中定义的静态局部变量无法局部化的原因。

二, .h头文件中的静态全局变量为什么可以被访问?

我们在学习C语言初期就直到,如果对一个全局变量使用static语句修饰的话,就可以把这个变量限制在本文件的访问域内,而无法被其他文件访问,但是这一点对于.h文件中无效,该访问还是可以访问?下面看一下实验

创建三个文件ori1.c, ori2.c, head.h

在ori1.c中写下以下内容

#include

extern int A;

extern int B;

int main() {

printf("A = %d\n", A);

printf("B = %d", B);

return 0;

}

在ori2.c中写下以下内容

#include

int A = 12;

static B = 13;

此时在head.h中不写入任何内容

编译运行

正如和我们学过的一样,出现了未定义的错误

undefined reference to `B'

collect2.exe: error: ld returned 1 exit status

静态全局变量不可以被其他变量修改

这时候我们给ori2.h添加两个函数

void getB() {

printf("B = %d\n", B);

}

void changeB(int num) {

B = num;

}

然后在ori1.c中去声明应用一下这两个函数

#include

extern int A;

extern void getB();

extern void changeB(int B);

int main() {

printf("A = %d\n", A);

getB();

changeB(1600);

getB();

return 0;

}

编译运行

>> A = 12

B = 13

B = 1600

虽然无法直接访问,但是可以定义ori2.c文件里面的函数去对该变量访问,这或许就是私有变量的雏形吧!

下面再来看看有关于.h中的全局变量,

由于我们已经知道了是完全插入的形式,那么我们可以理解到这个定义的静态全局变量是定义在引用它的文件里面

根据前文中定义在自己文件内部的静态全局变量只能被自己访问,那么结果自然显而易见了,

.h文件中的静态全局变量作用域是引用这个头文件的.c文件

自然而然的,我们应当明白,如果一个.h文件中定义过多的全局变量,那么这个全局变量被其他的变量引用的时候就会出现访问无指向的错误!重复定义

建议尽可能少在.h头文件中定义全局变量,或者静态全局变量

三,条件编译

C语言编译是把整个项目编译,而很多的.c文件都需要引用同一个函数,而正对于不同的系统又出现了不同的编译模式,如果说要把所有的.c文件头部都写入那些描述条件编译的代码,那么所有的代码写起来会复杂无比

所以把条件编译代码放在.h文件里面,直接配置好才是一个好的选择。

条件编译的例子

#include

#include

int main() {

#if _WIN64

system("color 0c");

printf("Hello World!");

#elif __linux__

printf("\033[22;31mHello World!\n\\033[22;30m\\");

#else

printf("Hello World!");

#endif

return 0;

}

#include

int main() {

#if _WIN64

printf("This is Windows!\n");

#else

printf("Unknown platform!\n");

#endif

#if __linux__

printf("This is Linux!\n");

#endif

return 0;

}

使用#ifdef判断宏是否被编译过,与之对应的还有一个#ifndef表示如果没有被定义的话、

#include

#include

int main(){

#ifdef _DEBUG

printf("正在使用 Debug 模式编译程序...\n");

#else

printf("正在使用 Release 模式编译程序...\n");

#endif

system("pause");

return 0;

}

#if后面接的是整形常量表达式,而#ifdef后面只能接宏名

又由于自己可以定义宏,自然而然的自己就可以配置出自己的项目的条件编译。

四,一点建议

用的多的函数放在.h头文件中定义声明。

尽量不要在.h头文件中设置全局变量,或者静态全局变量。

在.h头文件中使用条件编译控制项目的编译,简化代码书写成本。

c语言编程的头文件是什么,C语言头文件到底是什么?相关推荐

  1. 有没有c 或c语言的短期培训学校,根河学c语言编程,根河学c语言编程的学校,根河学c语言编程报个培训班怎么样...

    根河学c语言编程,根河学c语言编程的学校,根河学c语言编程报个培训班怎么样 首页 > 软件 > 根河学c语言编程 作者:镀金池   发布时间:2017-11-30 11:02 另外,尽早调 ...

  2. 8051单片机c语言编程模板,完美的8051单片机C语言编程模板.doc

    完美的8051单片机C语言编程模板.doc <8051单片机C语言编程模板> [程序开始处的程序说明] /***************************************** ...

  3. R语言编程艺术(4)R对数据、文件、字符串以及图形的处理

    本文对应<R语言编程艺术> 第8章:数学运算与模拟: 第10章:输入与输出: 第11章:字符串操作: 第12章:绘图 =================================== ...

  4. 华为c语言编程规范_单片机开发之C语言编程基本规范

    为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范.本标准规定了程序设计人员进行程序设计时必须遵循的规范.本规范主要针对单片机编程语言和08编译器而言,包括排版.注释.命名.变量 ...

  5. .net调用c++方法时如何释放c++中分配的内存_C/C++编程笔记:C语言编程知识要点总结!大一C语言知识点(全)...

    一.C语言程序的构成 与C++.Java相比,C语言其实很简单,但却非常重要.因为它是C++.Java的基础.不把C语言基础打扎实,很难成为程序员高手. 1.C语言的结构 先通过一个简单的例子,把C语 ...

  6. 两个变量实现查找坏环c语言,C/C++编程笔记:C语言编程知识要点总结!大一C语言知识点(全)...

    程序员无言 2020-07-07 一.C语言程序的构成 与C++.Java相比,C语言其实很简单,但却非常重要.因为它是C++.Java的基础.不把C语言基础打扎实,很难成为程序员高手. 1.C语言的 ...

  7. c语言编程规范总结,【技术小记 | C语言】C 语言编程规范

    image 欢迎大家访问我的个人博客:吴佳轶 | WuJiaYi,第一时间获取最新的文章. 规范制定说明 本套C语言编程规范为提高代码质量.便于维护.协同编码.可移植等特点而编写.要求所有参与编码人员 ...

  8. c语言编程输出指定范围的素数,C语言输出范围内所有素数

    用C语言输出100之间的所有质数 用C语言输出100之间的所有质数. 各位. 首先新建一个空白的c语言文件,引入头文件,头文件中包括math库,稍后会用到,建立主函数: 主函数上面新建一个判断素数的函 ...

  9. 单片机c语言编程入门下載,系列单片机C语言编程入门.pdf

    系列单片机C语言编程入门.pdf 本文由c h e n j u n j u n j u n 3贡献 p d f 文档可能在WAP端浏览体验不佳.建议您优先选择TXT,或下载源文件到本机 查看. 维普资 ...

  10. c语言编程测试char的整数生成,C语言编程实验

    <C语言编程实验>由会员分享,可在线阅读,更多相关<C语言编程实验(30页珍藏版)>请在人人文库网上搜索. 1.C语言实验习题7-1输出图形(10分)编写程序输出图形.第一行输 ...

最新文章

  1. 网络安全与机器学习(二):网络安全任务如何结合机器学习? 1
  2. 这个帖子要收藏,以后用得着--python 实时获取子进程输出
  3. Http协议(6)—安全HTTP
  4. a - 数据结构实验之串一:kmp简单应用_【在线教学示范课案例】数据结构(刘航)...
  5. mysql和mdy_Liunx下安装MySql
  6. USACO 6.1.3 Cow XOR
  7. drupal 7在一个form新增或者修改一个字段
  8. 华中数控机器人编程循环三次_华中数控:公司在数控技术上不断创新突破 在技术方面处于国内领先水平...
  9. SQL Server 2008 数据库快照
  10. 零基础学python书籍-清华大学出版社-图书详情-《零基础入门学习Python》
  11. openstack在xiandian界面登录提示无效证书_原产地证书自助打印来啦!
  12. 2、Charm Bracelet( poj 3624)简单0-1背包
  13. spring下配置dbcp,c3p0,proxool
  14. JavaScript快速入门
  15. php实现两张图片合成一张,如何把两张图片拼成一张
  16. 如何获取微信用户openid
  17. as常用固定搭配_as固定短语搭配
  18. 轨迹跟踪——二维轨迹跟踪
  19. 计算机病毒计算机软件系统故障,简要区分计算机病毒与软硬件故障问题
  20. Harbor docker login x509 certificate signed by unknown authority

热门文章

  1. c和java搞笑动图_拍一拍搞笑高清无水印表情包大全 拍一拍gif动图搞笑有趣表情包...
  2. 计算机联锁的应用领域,全电子计算机联锁系统优缺点
  3. 计算机联锁设备的操作,计算机联锁系统设备的键盘操作
  4. 清明上河图 HTML 代码
  5. 电子信息技术专业名词中英文对照(三)
  6. hutool依赖:BeanUtil工具类的使用:对象转对象、对象转map、map转对象
  7. Android开发眼镜店管理系统,智能眼镜店管理系统(基于BS架构互联网版)下载_智能眼镜店管理系统(基于BS架构互联网版)官方下载-太平洋下载中心...
  8. 4.5 第九讲 函数展开成幂级数及其应用
  9. linux刷显卡bios版本,一种Linux系统下显卡刷新BIOS的方法与流程
  10. PMP-项目进度管理