xx.h和xx.c的奥妙

示例代码:

/********************* A.c*********************/

#include "a.h"    //为什么要加?
void fun()
{
    return;
}

/******************** main.c********************/

#include "a.h"
int main( )
{
fun(); 
return 0;
}

为什么经常见xx.c里面include对应的xx.h?A.c中的#include "A.h"是否多余?
主要有两种原因:

①如果.c中的函数也需要调用同个.c中的其他函数,那么这个.c往往会include同名的.h,避免声明和调用顺序出现问题(C语言要求使用之前必须声明,而include同名.h一般会放在.c的开头)。

②.c中的函数中经常会使用了同名.h文件定义的宏,或者typedef定义的新类型。

有很多工程甚至把这种写法约定为代码规范,以规范出清晰的代码来。

由此,有很多工程甚至把这种写法约定为代码规范,以规范出清晰的代码来。以上示例中,显示是可有可无的。

从C编译器角度看,.h和.c只是后缀符号,毫无意义。换句话说,就是.h和.c没有必然联系。

1.预处理

预处理只是简单的替换,#include "xx.h"中所包含的完全展开到包含它的.c 文件中。.h只起到这个作用。

2.编译过程

以一个文件为基本的一个编译单元。一个.c文件生成一个.o文件,在编译阶段,只要.c或者包含的.h中已经声明的函数或变量,.c都会生成相应的.o文件。编译阶段对函数或变量的定义并无要求,所以在main.c中,即便void fun()是在A.c中定义的,但其包含的头文件中已经声明,即可顺利编译。

3.连接过程

将A.o和main.o结合起来,生成可执行文件。

若只是声明,没有在其他的.c中定义,连接时就会出错。也就是说若void fun()没有在A.c中定义,连接就会出错。不管是函数还是变量都是同样的道理。

随便提一下:若只是声明,而未定义。但是其声明的函数或变量并未使用,也是可以的连接通过的。

总结一下,.h一般放的是同名.c文件中定义的变量、数组、函数的声明,需要让.c外部使用的声明。这个声明有啥用?只是让需要用这些声明的地方方便引用。因为#include "xx.h"这个宏其实际意思就是把当前这一行删掉,把xx.h中的内容原封不动的插入在当前行的位置。只是一个简单的代码替换。由于想写这些函数声明的地方非常多(每一个调用xx.c中函数的地方,都要在使用前声明一下子),所以用#include "xx.h"这个宏就简化了许多行代码——让预处理器自己替换好了。也就是说,xx.h其实只是让需要写xx.c中函数声明的地方调用,至于include这个.h文件是谁,是.h还是.c,还是与这个.h同名的.c,都没有任何必然关系。

只要想调用xx.c中的某个函数,就直接包含include了xx.h,宏替换后也可能会出现了很多无用的声明,不过这样整个版面很清晰。多些声明(.h一般只用来放声明,而放不定义)没有任何坏处,不会影响编译。

xx.h和xx.c的奥妙相关推荐

  1. c语言是以文件为单位编译,c语言从头开始(三:编译器工作原理) (我们还可以自己编写头文件后缀是xx.h并把它当前代码文件所在目录我们要用就可以直接通过下面代码使用)...

    c语言从头开始(三:编译器工作原理) [[枫歌枫歌]c语言从头开始(三:编译器工作原理)]https://toutiao.com/group/6568056688174170628/?iid=1590 ...

  2. vue3封装时间计算-日期倒计时组件——还有XX天 第XX天

    vue3封装时间计算-日期倒计时组件--还有XX天 & 第XX天 & 年月日时分秒星期几方法的封装 & setup语法糖完整用法之reactive, ref, onMounte ...

  3. java newsize_JVM中的-Xms -Xmx -XX:newSize -XX:MaxnewSize -Xmn -XX:PermSize -XX:MaxPermSize区别介绍...

    一.配置参数使用条件 在不断重构代码的情况下,仍然不能解决内存溢出的问题(OutOfMemoryError等),这种情况下就需要使用JVM的配置参数对JVM运行时各个区域的内存情况进行相应的分配. 二 ...

  4. -XX:+UseParallelGC与 -XX:+UseParNewGC相关介绍

    首先看一个图(所有的垃圾回收器,以及工作的堆空间) 对于我们默认(jdk1.7)使用parallel 垃圾回收器,old区就是使用的是parallel old, yong区使用的是parallel S ...

  5. http://www.od85c.com.cn/html/,OllyDbg script for unpacking Enigma 4.xx and 5.xx

    [Asm] 纯文本查看 复制代码// Enigma Protector 4.xx and 5.XX unpacker by GIV (some parts are from LCF-AT Altern ...

  6. java xms512m_安装版的tomcat设置JAVA_OPTS=-Xms128M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=512M...

    tomcat如果是通过windows服务启动,执行的是bin\tomcat.exe.他读取注册表中的值,而不是catalina.bat的设置.解决办法:修改注册表HKEY_LOCAL_MACHINE\ ...

  7. 【Java】计算从你的出生日期到现在相隔了多少天,多少时,XX分,XX秒。

    计算从你的出生日期到现在相隔了多少天,多少时,XX分,XX秒.(例如:"XX学号为XXXXX,出生日期为:XX年XX月XX日,现在时间为:XX年XX月XX日,出生日期到现在相隔了多XX天,X ...

  8. x+=x-=x*x; 和 x-=x*x; x+=x;

    2019独角兽企业重金招聘Python工程师标准>>> 原问题: 第一种情况: int x=6; 问执行下列语句后x的值 x+=x-=x*x; 这个答案是-24. 首先明确一点赋值操 ...

  9. bash xx.sh与sh xx.sh以及./xx.sh的区别

    在ubuntu中,sh只是bash的一个链接,执行的程序都是一样的,命令解释器是一样的.但bash xx.sh和./xx.sh和sh xx.sh还是有不同的,bash xx.sh和sh xxx.sh都 ...

最新文章

  1. 轻松学Pytorch – 行人检测Mask-RCNN模型训练与使用
  2. python walk 遍历文件夹 文件大小
  3. ab url 带参数 测试
  4. python 第三方库 工具
  5. Unit9 Mangement Strategies—— I
  6. ElasticSearch 索引模块——集成IK中文分词
  7. ATS读小文件(内存命中)
  8. 仿小说蓝色小说网站导航引流网站源码 带手机版
  9. bzoj 1016: [JSOI2008]最小生成树计数
  10. 大数据笔试面试题(转载)
  11. pam php水解加碱,2钻井液化学.ppt
  12. Java如何使用IP代理
  13. 对今日头条问答部分的预测-未来可能会挂掉
  14. 如何实现罗克韦尔PLC AB1756的远程监控数据采集?
  15. Panabit镜像功能配合wireshark抓包的方法
  16. 初学verilog必看
  17. jsp+spring+hibernate
  18. 网站建设要怎么选择域名?有哪些小技巧?
  19. Gox语言中使用内存虚拟文件系统提升IO处理速度-GX43.1
  20. peda 官方帮助文档

热门文章

  1. 一条命令搞定黑苹果双系统时差
  2. 2021年最新版Web前端学习路线图-前端小白入门必读-推荐
  3. 富文本样式文字图片处理
  4. 教程:在C#中创建带有表格、图表、图片的PPT演示文稿
  5. java实现日期加一天
  6. 记录一下iphone7s维修过程
  7. 汇编语言中xor指令_汇编语言XOR指令:对两个操作数进行逻辑(按位)异或操作(推荐)...
  8. 实验室设备测量超低偏置电流的实用技巧
  9. python代码提示太弱了_10行Python代码制作群聊提醒小助手,再也不怕漏掉消息了...
  10. 牛牛的算术(公式推导)