1.预处理器:

预处理器不是编译器的组成部分,但是它是编译过程中一个单独的步骤。简言之,C 预处理器只不过是一个文本替换工具而已,它们会指示编译器在实际编译之前完成所需的预处理。

我们将把 C 预处理器(C Preprocessor)简写为 CPP。

所有的预处理器命令都是以井号(#)开头。它必须是第一个非空字符,为了增强可读性,预处理器指令应从第一列开始。具体的列表可以在网上找到,这里不再复述。

a.几个常用的:

#define MAX_ARRAY_LENGTH 20  (所有的MAX_ARRAY_LENGTH 替换为 20)

#include <stdio.h> 

#include "myheader.h"   (这两行指令告诉 CPP 从系统库中获取 stdio.h,并添加文本到当前的源文件中。下一行告诉 CPP 从本地目录中获取 myheader.h,并添加内容到当前的源文件中。)

b.预定义宏:

不能修改的预定义宏,可以根据情况使用:

__DATE__    当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。

__TIME__       当前时间,一个以 "HH:MM:SS" 格式表示的字符常量

__FILE__        这会包含当前文件名,一个字符串常量。

__LINE__      这会包含当前行号,一个十进制常量。

__STDC__     当编译器以 ANSI 标准编译时,则定义为 1。

c.预处理器运算符:

宏延续运算符(\):一个宏通常写在一个单行上。但是如果宏太长,一个单行容纳不下,则使用宏延续运算符.

字符串常量化运算符(#):在宏定义中,当需要把一个宏的参数转换为字符串常量时,则使用字符串常量化运算符(#)。在宏中使用的该运算符有一个特定的参数或参数列表.

标记粘贴运算符(##):宏定义内的标记粘贴运算符(##)会合并两个参数。它允许在宏定义中两个独立的标记被合并为一个标记。

d.参数化的宏:

CPP 一个强大的功能是可以使用参数化的宏来模拟函数:

int square(int x)

{

return x * x;

}

这段代码可以用宏重写:

#define square(x) ((x) * (x))      //注意所有的参数都要括号,不然运算错误

2.头文件调用:

头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。

在程序中要使用头文件,需要使用 C 预处理指令 #include 来引用它。前面我们已经看过 stdio.h 头文件,它是编译器自带的头文件。

引用头文件相当于复制头文件的内容,但是我们不会直接在源文件中复制头文件的内容,因为这么做很容易出错,特别在程序是由多个源文件组成的时候。

A simple practice in C 或 C++ 程序中,建议把所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件。

a.引用:

#include <file>  //引用的是编译器的类库路径里面的头文件。

或者 

#include "file"  //引用的是你程序目录的相对路径中的头文件,如果在程序目录没有找到引用的头文件则到编译器的类库路径的目录下找该头文件。

都可以。

b.具体操作:

#include 指令会指示 C 预处理器浏览指定的文件作为输入。预处理器的输出包含了已经生成的输出,被引用文件生成的输出以及 #include 指令之后的文本输出。

int x;

#include "header.h"     // 假如头文件里只有“char *test (void);” ,这一段就会被那句话替代

int main (void) {

puts (test ());

}

c. 只引用一次:

如果一个头文件被引用两次,编译器会处理两次头文件的内容,这将产生错误。为了防止这种情况,标准的做法是把文件的整个内容放在条件编译语句中.

#ifndef HEADER_FILE

#define HEADER_FILE

。。。 //头文件列表

#endif

d.有条件的引用:

有时需要从多个不同的头文件中选择一个引用到程序中。例如,需要指定在不同的操作系统上使用的配置参数:

#if SYSTEM_1

# include "system_1.h"

#elif SYSTEM_2

# include "system_2.h"

#elif SYSTEM_3

...

#endif

但是如果头文件比较多的时候,这个方法不是很好,所以我们用下面:

#define SYSTEM_H "system_1.h"

...

#include SYSTEM_H

SYSTEM_H 会扩展,预处理器会查找 system_1.h,就像 #include 最初编写的那样。SYSTEM_H 可通过 -D 选项被您的 Makefile 定义。

sub:在有多个 .h 文件和多个 .c 文件的时候,往往我们会用一个 global.h 的头文件来包括所有的 .h 文件,然后在除 global.h 文件外的头文件中 包含 global.h 就可以实现所有头文件的包含,同时不会乱。方便在各个文件里面调用其他文件的函数或者变量。

C学习笔记(9)--- 预处理器,头文件的更多相关文章

  1. C和指针 第十四章 预处理器 头文件

    编写一个C程序,第一个步骤称为预处理,预处理在代码编译之前,进行一些文本性质的操作,删除注释.插入被include的文件.定义替换由#define定义的符号,以及确定代码的部分内容是否应该按照条件编译 ...

  2. [转]Linux学习笔记——例说makefile 头文件查找路径

    0.前言     从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己动手写一个makefile总觉得非常吃力.所以特意借助 ...

  3. Linux学习笔记——例说makefile 头文件查找路径

    0.前言     从学习C语言開始就慢慢開始接触makefile,查阅了非常多的makefile的资料但总感觉没有真正掌握makefile,假设自己动手写一个makefile总认为非常吃力.所以特意借 ...

  4. VS2010遇到fatal error C1083: 无法打开预编译头文件:“xxx.pch”: No such file or directory

    对C++和VS2010非常不熟悉,但是无奈赶着项目,只能看了点基础就上手,然后就碰到这个问题了. 原因分析: http://bbs.csdn.net/topics/340191697?page=1 编 ...

  5. fatal error C1083: 无法打开预编译头文件:“Debug\a.pch”:No such file or directory

    一.解决方法 右键点击你创建的项目,选择“属性标签”点击属性,弹出“项目属性页”,在左侧找到以下位置  配置属性 -->  C/C++  --> 预编译头,并选择它:在右边的菜单中选择 “ ...

  6. App开发流程之增加预编译头文件

    在继续增加预编译头文件前,先稍等. Xcode为我们创建了一个模板项目,很棒!但有一点不太令人满意,问题就在下图中: 这是一个新项目的初始文件目录,几乎所有文件都在同一级目录下,随着项目文件数量急速增 ...

  7. 预编译头文件 StdAfx.h

    预编译头文件: 最常见的使用场景就是 StdAfx.h 文件,在这个文件中包含常用的头文件,比如windows.h,cstdio,string,别的 .cpp 文件去包含 StdAfx.h 头文件.编 ...

  8. C++ 预编译头文件

    1.解决什么问题? C++ 编译器是单独,分别编译的,每个cpp文件,进行预编译(也就是对#include,define 等进行文本替换),生成编译单元.编译单元是一个自包含文件,C++编译器对编译单 ...

  9. 【转】预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)

    用VC++ 2008 编写C语言程序,编译出现错误: 预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反) 解决方法: 建工程时 建立空项目 或者在项目设置里关闭预编 ...

  10. xcode 预编译头文件

    xcode 预编译头文件 cocos2d-prefix.pch  #import <Foundation/Foundation.h>

随机推荐

  1. 转载 could not find a getter for ... in class ... 异常的原因解析

    可能原因如下: 1.真的没有写getter方法(发生几率:1%) 2.*.hmb.xml文件中的属性名和pojo不一致(*.hbm.xml和*.java没衔接好,不一致),字段属性没有正确配置,比如, ...

  2. Centos7 下安装python3及卸载

    一.安装python3 1.安装依赖包 yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel read ...

  3. 微信小程序中换行,空格(多个空格)写法

    在小程序中HTML的网页实体无法正常使用,小程序中的写法为: 一.空格,换行 <text>你好!\t七月流火啊!\n我在下一行</text> \t 空格( 多个只会显示一个空格 ...

  4. axel 多线程下载工具

    yum install axel-2.4-9.el7.x86_64 -y # 选项 --max-speed=x , -s x 最高速度x --num-connections=x , -n x 连接数x ...

  5. 浅谈Django基础(HttpResponse、render、redirect)

    1. 使用之前先导入他们 from django.shortcuts import HttpResponse, render, redirect 2. HttpResponse: 它是作用是内部传入一 ...

  6. 高通电池管理基于qpnp-vm-bms电压模式

    CV:Constant Voltage恒压 SMMB charger:Switch-ModeBattery Charger and Boost peripheral开关模式电池充电器和升压外围设备 O ...

  7. HashMap与HashTable的区别和理解

    Hashmap的理解 1:HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.HashMap储存的是键值对,HashMap很快.此类不保 ...

  8. 7.SourceTree 的使用

    SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端管理工具,同时也是Mn版本控制系统工具.支持创建.克隆.提交.push.pull 和合并等操作. 下载路 ...

  9. 最小化MarkdownPad 2安装体积(win10)

    一.原因 MarkdownPad2在Win10当中可能无法正常运行,右侧预览界面会出现错误"This view has crashed!"查阅官网FAQ得知大多数情况下安装Awes ...

  10. Java内存中的常量池

    1,java内存模型简介 <深入理解java虚拟机>里将java内存分为如下五个模块: 堆-堆是所有线程共享的,主要用来存储对象. 其中,堆可分为:新生代和老年代两块区域.使用NewRat ...