在嵌入式系统编程中不管是内核的驱动程序还是应用程序的编写,涉及到大量的预处理与条件编译,这样做的好处主要体现在代码的移植性强以及代码的修改方便等方面。因此引入了预处理与条件编译的概念。预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。

中文名

C语言预处理程序

外文名

C language preprocessor

分    类

计算机指    令

宏定义 文件包含 条件编译

控    制

指令

优    势

代码的移植性强,修改方便

应    用

嵌入式系统编程

C语言预处理程序简介

编辑

在嵌入式系统编程中不管是内核的驱动程序还是应用程序的编写,涉及到大量的预处理与条件编译,这样做的好处主要体现在代码的移植性强以及代码的修改方便等方面。因此引入了预处理与条件编译的概念。预处理(或称预编译)是指在进行编译的第一遍扫描(词法扫描和语法分析)之前所作的工作。预处理指令指示在程序正式编译前就由编译器进行的操作,可放在程序中任何位置。

预处理是C语言的一个重要功能,它由预处理程序负责完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分作处理,处理完毕自动进入对源程序的编译。C语言提供多种预处理功能,主要处理#开始的预编译指令,如宏定义(#define)、文件包含(#include)、条件编译(#ifdef)等。合理使用预处理功能编写的程序便于阅读、修改、移植和调试,也有利于模块化程序设计。

C语言预处理程序功能

编辑

在集成开发环境中,编译,链接是同时完成的。其实,C语言编译器在对源代码编译之前,还需要进一步的处理:预编译。预编译的主要作用如下:

1、将源文件中以”include”格式包含的文件复制到编译的源文件中。

2、用实际值替换用“#define”定义的字符串。

3、根据“#if”后面的条件决定需要编译的代码。

C语言预处理程序工作方式

编辑

预处理的行为是由指令控制的。这些指令是由#字符开头的一些命令。

#define指令定义了一个宏---用来代表其他东西的一个命令,通常是某一个类型的常量。预处理会通过将宏的名字和它的定义存储在一起来响应#define指令。当这个宏在后面的程序中使用到时,预处理器”扩展”了宏,将宏替换为它所定义的值。

#include指令告诉预处理器打开一个特定的文件,将它的内容作为正在编译的文件的一部分“包含”进来。例如:下面这行命令:

#include指示预处理器打开一个名字为stdio.h的文件,并将它的内容加到当前的程序中。

预处理器的输入是一个C语言程序,程序可能包含指令。预处理器会执行这些指令,并在处理过程中删除这些指令。预处理器的输出是另外一个程序:原程序的一个编辑后的版本,不再包含指令。预处理器的输出被直接交给编译器,编译器检查程序是否有错误,并经程序翻译为目标代码[1]

C语言预处理程序指令

编辑

C语言预处理程序类型

大多数预处理器指令属于下面3种类型:

1、宏定义:#define 指令定义一个宏,#undef 指令删除一个宏定义。

2、文件包含:#include指令导致一个指定文件的内容被包含到程序中。

3、条件编译:#if,#ifdef,#ifndef,,#elif,#else 和#dendif 指令可以根据编译器可以测试的条件来将一段文本包含到程序中或排除在程序之外。

剩下的#error,#line和#pragma指令更特殊的指令,较少用到。

C语言预处理程序规则

1、指令都是以#开始。#符号不需要在一行的行首,只要她之前有空白字符就行。在#后是指令名,接着是指令所需要的其他信息。

2、在指令的符号之间可以插入任意数量的空格或横向制表符。

3、指令总是第一个换行符处结束,除非明确地指明要继续。

4、指令可以出现在程序中德任何地方。我们通常将#define和#include指令放在文件的开始,其他指令则放在后面,甚至在函数定义的中间。

5、注释可以与指令放在同一行[2]

C语言预处理程序宏定义

编辑

C语言预处理程序无参数的宏

无参数的宏定义格式:#define 宏名 字符串,各部分的含义如下:

1、#:表示这是一条预处理命令(凡是以“#”开始的均为预处理命令)。

2、define:关键字“define”为宏定义命令。

3、宏名:是一个标示符,必须符合C语言标示符的规定,一般以大写字母标示宏名。

4、字符串:可以是常数,表达式,格式串等。在前面使用的符号常量的定义就是一个无参数宏定义。

需要注意的是,预处理命令语句后面一般不会添加分号,如果在#define最后有分号,在宏替换时分号也将替换到源代码中去。在宏名和字符串之间可以有任意个空格。例如:#define PI 3.14。

在使用宏定义时,还需要注意以下几点:

1、宏定义是宏名来表示一个字符串,在宏展开时又以该字符串取代宏名。这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。

2、宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。

3、宏名在源程序只能够若用引号括起来,则预处理程序不对其作宏替换。

4、宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层替换。

5、习惯上宏名可用大写字母表示,以方便与变量区别。但也允许用小写字母。

C语言预处理程序带参数的宏

#define命令定义宏时,还可以为宏设置参数。与函数中的参数类似,在宏定于中的参数为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,还要用实参去代换形参。

带参宏定义的一般形式为:#define 宏名(形参表) 字符串,在定义带参数的宏时,宏名和形参表之间不能有空格出现,否则,就将宏定义成为无参数形式,而导致程序出错。例如:#define ABS(x) (x)<0?-(x):(x)。

以上的宏定义中,如果x的值小于0,则使用一元运算符(-)对其取负,得到正数。

带参的宏和带参的函数相似,但其本质是不同的。使用带参宏时,在预处理时将程序源代码替换到相应的位置,编译时得到完整的目标代码,而不进行函数调用,因此程序执行效率要高些。而函数调用只需要编译一次函数,代码量较少,一般情况下,对于简单的功能,可使用宏替换的形式来使用。

C语言预处理程序文件包含

编辑

当一个C语言程序由多个文件模块组成时,主模块中一般包含main函数和一些当前程序专用的函数。程序从main函数开始执行,在执行过程中,可调用当前文件中的函数,也可调用其他文件模块中的函数。如果在模块中要调用其他文件模块中的函数,首先必须在主模块中声明该函数原型。一般都是采用文件包含的方法,包含其他文件模块的头文件。文件包含中指定的文件名即可以用引号括起来,也可以用尖括号括起来,格式如下是#include< 文件名>或#include“文件名”如果使用尖括号<>括起文件名,则编译程序将到C语言开发环境中设置好的 include文件中去找指定的文件。因为C语言的标准头文件都存放在include文件夹中,所以一般对标准头文件采用尖括号;对编程自己编写的文件,则使用双引号。如果自己编写的文件不是存放在当前工作文件夹,可以在#include命令后面加在路径。

#include命令的作用是把指定的文件模块内容插入到#include所在的位置,当程序编译链接时,系统会把所有#include指定的文件链接生成可执行代码。文件包含必须以#开头,表示这是编译预处理命令,行尾不能用分号结束。#include所包含的文件,其扩展名可以是“.c”,表示包含普通C语言源程序。也可以是 “.h”,表示C语言程序的头文件。C语言系统中大量的定义与声明是以头文件形式提供的。通过#define包含进来的文件模块中还可以再包含其他文件,这种用法称为嵌套包含。嵌套的层数与具体C语言系统有关,但是一般可以嵌套8层以上。

C语言预处理程序条件编译

编辑

预处理器还提供了条件编译功能。在预处理时,按照不同的条件去编译程序的不同部分,从而得到不同的目标代码。使用条件编译,可方便地处理程序的调试版本和正式版本,也可使用条件编译使程序的移植更方便。

C语言预处理程序使用#if

与C语言的条件分支语句类似,在预处理时,也可以使用分支,根据不同的情况编译不同的源代码段。

#if 的使用格式如下:

#if 常量表达式

程序段

#else

程序段

#endif

该条件编译命令的执行过程为:若常量表达式的值为真(非0),则对程序段1进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下完成不同的功能。

#if 预编译命令还可使用多分支语句格式,具体格式如下:

#if 常量表达式 1

程序段 1

#elif 常量表达式 2

程序段 2

… …

#elif 常量表达式 n

程序段 n

#else

程序段 m

#endif

C语言预处理程序使用#ifdef和#ifndef

在上面的#if 条件编译命令中,需要判断符号常量定义的具体值。在很多情况下,其实不需要判断符号常量的值,只需要判断是否定义了该符号常量。这时,可不使用#if命令,而使用另外一个预编译命令———#ifdef.

#ifdef命令的使用格式如下:

#ifdef 标识符

程序段 1

#else

程序段 2

#endif

其意义是,如果#ifdef后面的标识符已被定义过,则对“程序段1”进行编译;如果没有定义标识符,则编译“程序段2”。一般不使用#else及后面的“程序2”。

而#ifndef的意义与#ifdef相反,其格式如下:

#ifndef 标识符

程序段 1

#else

程序段 2

#endif

其意义是:如果未定义标识符,则编译“程序段1”;否则编译“程序段2”。

C语言预处理程序使用#defined和#undef

与#ifdef 类似的,可以在#if命令中使用define来判断是否已定义指定的标识符。例如:

#if defined 标识符

程序段 1

#endif

与下面的标示方式意义相同:

#ifdef 标识符

程序段 1

#endif

也可使用逻辑运算符,对defined取反。例如:

#if ! define 标识符

程序段 1

#endif

与下面的标示方式意义相同。

#ifndef 标识符

程序段 1

#endif

在#ifdef和#ifndef命令后面的标识符是使用#define进行定义的。在程序中,还可以使用#undef取消对标识符的定义,其形式为:

#undef 标识符

例如:

#define MAX 100

……

#undef MAX

在以上代码中,首先使用#define定义标识符MAX,经过一段程序代码后,又可以使用#undef取消已定义的标识符。使用#undef命令后,再使用#ifdef max,将不会编译后的源代码,因为此时标识符MAX已经被取消定义了。

c语言继续程序指令,C语言预处理程序相关推荐

  1. c语言编程培训ppt,C语言入门经典-C语言编程.ppt

    <C语言入门经典-C语言编程.ppt>由会员分享,可在线阅读,更多相关<C语言入门经典-C语言编程.ppt(27页珍藏版)>请在人人文库网上搜索. 1.第01章 C语言编程,C ...

  2. c语言入门经典doc,C语言入门经典C语言编程.ppt

    C语言入门经典C语言编程.ppt 第01章 C语言编程,C语言是一种功能强大.简洁的计算机语言,通过它可以编写程序,指挥计算机完成指定的任务.我们可以利用C语言创建程序即一组指令,并让计算机依指令行事 ...

  3. 编程入门c语言ppt,C语言入门经典-C语言编程.ppt

    <C语言入门经典-C语言编程.ppt>由会员分享,可在线阅读,更多相关<C语言入门经典-C语言编程.ppt(27页珍藏版)>请在装配图网上搜索. 1.第01章 C语言编程,C语 ...

  4. 为什么除了Go语言, 其他类C语言都是垃圾[翻译][转]

    2019独角兽企业重金招聘Python工程师标准>>> 英文原文: http://www.syntax-k.de/projekte/go-review 原始翻译: http://ww ...

  5. C语言程序设计----初识C语言与程序设计

    对于初次学习C语言程序设计,我们要了解到C语言程序设计的学习包括两个方面: 语法规则的学习和程序设计方法的学习:学习计算机语言和程序设计的目的: 就是要学会用计算机语言编写解决实际问题的程序. 一.C ...

  6. r语言 断轴 画图_R语言基础画图/绘图/作图

    R语言基础画图 R语言免费且开源,其强大和自由的画图功能,深受广大学生和可视化工作人员喜爱,这篇文章对如何使用R语言作基本的图形,如直方图,点图,饼状图以及箱线图进行简单介绍. 0 结构 每种图形构成 ...

  7. c语言 字母 八进制表示'/1011',C语言C语言第一课:C语言概述为什么学习C语言怎样学习C语言.DOC...

    [摘要]C语言 第一课: C语言概述 为什么学习C语言 怎样学习C语言 参考资料 ----------------------------------------------------------- ...

  8. 学单片机需要多少C语言基础,C语言单片机编程教程

    很多学员和朋友经常找我给他们推荐C语言的书,他们可能想和我当年一样,闷头大干一场,学个几个月的C语言,把C语言吃透,再开始单片机程序开发! 别!别!别! 大家千万别这么干,我当年自学了3个月的C语言, ...

  9. 为什么可以说Java语言是准动态语言?

    什么是动态语言? 动态语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化.比如JavaScript便是一个典型的动态语言. 除此之外如Ruby.Python ...

最新文章

  1. linux c fopen open 互相转换 文件指针 到 文件描述符 FILE* 转 FD
  2. Linux疑难杂症解决方案100篇(十八)-Linux 或 Windows 上实现端口映射
  3. mysql的电话面试题_以往百度电话面试题
  4. 爬取json Swaggerui界面
  5. Ubuntu修改/删除主目录下的中文文件夹
  6. 大数据分析需要什么技术架构
  7. 美团程序员吐槽公司蹲位:如厕5分钟找坑两小时
  8. 越是经济下行,越是赚大钱的好机会!
  9. 盒马销量预测核心算法的技术演进
  10. linux安装fdfs
  11. efi shell的英文介绍_EFI和EFI Shell命令简介
  12. Oracle SQL 批量修改资料库邮箱后缀名称
  13. Python 入门学习路线
  14. 超全总线控制方式总结
  15. vmware 架设网站无法打开解决办法
  16. 微信小程序数据拼接_最佳方式实现微信小程序分页加载数据
  17. Android 学习之垂直切换的圆角 Banner 和垂直指示器
  18. mysql5.6安装sys库_编译安装MySQL5.6.23
  19. 分享:Java 开发精美艺术二维码
  20. 北邮 操作系统(一)

热门文章

  1. 无人机图像处理工具更新——多线程优化版
  2. Scala入门到精通——第十七节 类型参数(一)
  3. 广告点击率常用模型的优点和缺点
  4. 一文让你彻底理解 Java HashMap
  5. js验证input输入框(字母,数字,符号,中文)
  6. (十四)Java springcloud B2B2C o2o多用户商城 springcloud架构- Spring Cloud构建分布式电子商务平台...
  7. ORACLE SQL Developer日期显示格式设置
  8. 《javascript高级程序设计》笔记:Function类型
  9. 中国物联网产业RFID发展机遇分析
  10. js学习笔记15----子节点和兄弟节点的操作