预处理过程:头文件 您所在的位置:网站首页 c程序中头文件的作用 预处理过程:头文件

预处理过程:头文件

2023-07-27 21:04| 来源: 网络整理| 查看: 265

本文学习编译器在预处理过程中对头文件的处理。Hightec编译器版本是tricore v4.9.1.0。博主在板块就经常提到头文件,本文会从编译器的角度对头文件进行学习。

文章目录 1 Include语法2 编译器对Include的处理3 头文件的搜索路径4 只加载一次头文件4.1 问题4.2 通过条件编译只加载一次头文件 5 总结

1 Include语法

头文件一般包含C语言的声明和宏定义。在C语言源文件中,通常在最上面用#include指令调用,俗称为包含某个头文件。

头文件一般分为系统头文件和用户头文件。

系统头文件通常是用来调用系统库,在#include后面要用尖括号。 #include 用户头文件中通常是函数、全局变量的外部声明, 宏定义,结构体定义,类型定义等。用户头文件起到了一个接口的作用,将不同的独立C文件通过头文件联系起来。用户头文件在#include后面要用引号。 #include "file" 2 编译器对Include的处理

调用编译器对某个C源文件进行预处理时,如果编译器看到了#include指令,就会先扫描一下#include后的头文件,然后把头文件展开到#include指令的位置。

为了直观地体会到这个过程,可以自己创建一些文件,然后调用编译器进行预处理。

1)首先,创建一个 header.h 头文件如下; 在这里插入图片描述 在这个头文件中对test函数进行了外部声明。

2)然后再建立一个program.c文件,如下; 在这里插入图片描述 在C文件中显示定义了一个变量x,然后包含了header.h这个头文件,然后定义了test2函数。

3)通过如下命令行调用编译器,对当前目录下地 program.c 代码进行预处理。

tricore-gcc -E program.c -o program.i

在这里插入图片描述 4)在生成的.i文件中,可以看到 header.h 头文件的内容被插入到了 program.c 源文件中; 在这里插入图片描述 另外,头文件中也可以嵌套包含头文件,这样的话就会一层一层地展开。

3 头文件的搜索路径

上一章是把头文件和源文件放在了一个路径下,通过编译器进行预处理。如果不特别地指出,编译器会在几个安装路径下和当前路径搜索头文件。如果要指定搜索头文件的路径,可以用 -I 参数指明.

例如,把头文件放在inc文件夹中,如下: 在这里插入图片描述 这样的话,命令行就要写成下面的样子。

tricore-gcc -E program.c -o program.i -I ./inc

如果不加 -I 参数,编译器会报出找不到头文件的错误,如下图。 在这里插入图片描述 所以工作中如果看到了这种错误,就要考虑是头文件没加到路径中,还是路径没加到命令行中。

4 只加载一次头文件 4.1 问题

实际项目中会有大量地头文件嵌套,一不小心就会重复包含了头文件。重复包含头文件会有两个问题:一方面如果头文件中有结构体定义,在编译的阶段会报错(预处理过程是不会报错的);另一方面,就算没有重复定义的报错,重复加载也会浪费时间。

对于结构体重复定义的报错,可以自己复现出来。

1)首先把第2章中的头文件稍作修改,定义一个结构体。 在这里插入图片描述 2)然后在C文件中包含两次该头文件。 在这里插入图片描述 3)再通过命令行调用编译器,对源文件进行预处理。注意这里没有 -E 参数,因为结构体重复定义是在编译过程中报错。

tricore-gcc program.c -o program.i

在这里插入图片描述 如上图中,指明了struct1这个结构体类型重复定义了。

4.2 通过条件编译只加载一次头文件

有一种标准的方法解决上述问题,就是将源文件的整个内容包含在条件编译中,范例如下:

/* File foo. */ #ifndef FILE_FOO_SEEN #define FILE_FOO_SEEN the entire file #endif /* !FILE_FOO_SEEN */

其中 #ifndef 表示如果后面的宏没有被定义,则执行下面到#endif之前的内容。当头文件第一次被包含的时候,还没有定义 FILE_FOO_SEEN 这个宏,就会先定义这个宏,扫描头文件的内容(也就是上述范例的 the entire file)然后展开到源文件中;当头文件第二次被包含的时候,由于第一次定义了这个宏,所以就直接跳到 #endif 了,也就不会再加载一次了。

对4.1中的源文件做预处理,就可以看到对比结果。

1)当没有用条件编译的时候,预处理后会把结构体类型的定义加载两次,也就导致了后面编译过程的报错。 在这里插入图片描述 2)在头文件中加上条件编译如下。 在这里插入图片描述 然后再进行一次预处理,输出的i文件如下图。这样就只有一个结构体定义了。 在这里插入图片描述

5 总结

本文研究了预处理过程中对头文件的处理,有助于理解头文件的作用。

>>返回个人博客总目录



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有