所谓预处理,是指源文件在进行编译的第一遍扫描之前所作的工作,由预处理程序完成。当对一个源文件进行编译时,系统将自动引用预处理程序对源程序中的预处理部分进行处理,处理完毕自动进入对源程序的编译。

在前面的章节中已多次出现了#define与#include,在C语言源程序中这些以“#”开头的命令都放在函数之外,而且一般都放在源文件的前面,这些都是预处理指令。

变量式宏定义也就是不带参数的宏定义,其定义的一般形式为:

#define  标识符  字符串

例如在程序中需要经常使用圆周率完成一定的功能,这个时候,当然可以反复使用3.1415926这个浮点数穿插到程序中,但是书写过于频繁,可能会因为疏忽发生错误,如果程序在更新过程要求提高或者降低圆周率的精度,那需要修改程序的工作量是相当大的,怎么办才能简化操作呢?这里,就可以使用变量式宏定义,具体如下:

#define PI 3.1415926

这个宏定义的作用是:使用标识符PI来代表程序中“3.1415926”的这个字符串,在编译预处理时,将程序中在该命令以后出现的所有的PI都用“3.1415926”代替,不仅使用简单可避免错误,而且还可以做到一改全改的效果。

简单的变量式宏定义,在上一小节通过几个范例较为详细地说明了其适用的各种情况。和变量定义一样,宏也是可以嵌套定义的。例如:

#define A (1+2)

#define B A*A

#define C B+B

先定义了A,然后定义B,最后又定义了C,环环相套,次序不能颠倒。宏展开后如下:

#define A (1+2)

#define B (1+2)*(1+2)

#define C (1+2)*(1+2)+ (1+2)*(1+2)

文件中的宏定义并非是从定义就有效到文件结束,可以圈定宏定义的作用范围,使用的方法是:

#define    /*宏定义开始*/

……   /*宏定义范围*/

#undef    /*宏定义结束*/

其定义的一般形式为:

#define  标识符(参数列表)  字符串

字符串中包含标识符中的参数,参数列表可由一个或者多个参数组成。因为外观像调用含义一样,所以称之为函数式宏定义,也可以称为带参数的宏定义。

通常宏定义必须是单行的,但是也可以使用多行来定义一个宏,定义的方法就是使用反斜杠“\”。比如:

#define min(x,y)\                /*多行宏定义开始*/

((x)

这个指令写在两行中,第2行为了美观,插入了一些空白符,使用的是空格。但是需要注意的是:第1行的反斜杠“\”必须放在该行的结尾,也就是输入了“\”后,紧接着的就是回车。

文件包含指令的功能是把指定的文件插入该指令行位置取代该指令行,从而把指定的文件和当前的源程序文件连成一个源文件。在程序设计中,文件包含是很有用的。一个大的程序可以分为多个模块,由多个程序员分别编程。有些公用的符号常量或宏定义等可单独组成一个文件,在其他文件的开头用包含指令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用部分,从而节省时间,并减少出错。

通常以头文件来编写这些被包含的文件,也就是以.h作为这些文件的扩展名,当然不是非要这样命名才可以。也可以使用.c为扩展名,或者干脆就不写扩展名,这样做都是允许的,只是使用.h更普遍,因为它能够表示该文件的性质。

文件包含#include指令的作用,就是把文件按照顺序合并成一个文件,这是预处理阶段。在编译时,对已经经过预处理的文件myfile.c作为一个源文件单位进行编译。

也可以看出了文件包含的意义,既提高了公用文件的使用率,节省了开发的时间,也减小了程序出错误的几率。

条件编译形式

调试中使用条件编译

文件嵌套包含和条件编译

assert()宏

一般的条件编译形式如下。

1. #ifdef 形式

作用是标识符已经被定义,则对程序段1进行编译,否则编译程序段2。

2. #ifndef形式

这种形式的条件编译与第1种形式相同,内容相反。只是ifdef替换成了ifndef,即如果标识符没有被定义过,就会编译程序段1,否则就编译程序段2。

每个大型程序都要经历内部测试和外部测试,最终发布版,即使是发布后,应用程序还会存在bug,需要修改完善。程序开发不是一蹴而就的,需要反复地修改完善。修改代码,就避免不了使用调试功能,输出丰富的调试信息有助于尽快地完成程序的修复。

可以在程序中输出参数的值,判断什么位置出现了问题,但是如果程序调试结束再一一删除输出值的语句,工作量会比较大。因此特别是对于大型程序,就可以在调试中使用宏。

由于嵌套包含文件的原因,一个头文件可能会被多次包含在一个源文件中,而使用条件指示符就可以防止这种头文件的重复处理。

只要不存在两个必须包含的头文件,要检查一个同名的预处理器常量这样的情形,这个策略就能够很好地运作。#ifndef指示符常被用来判断一个预处理器常量是否已被定义,以便有条件地包含程序代码。#ifndef 除了用于防止重复包含,还可以用于针对不同环境的条件编译。

assert()宏是在标准函数库头文件中定义的,称为断言。assert()宏可以让你在程序中插入任何表达式,用来诊断表达式的值是否为false,也就是为0。作为assert()宏的参数的表达式的结果是一个整型数据。

例如:

assert(a==b);

当a和b相等时,表达的结果是1,也就等同于true;如果a和b不等,结果就是0,也就是false,然后可根据结果决定是否终止程序。当程序出现异常时,可以使用abort()函数以非正常方式立即结束应用程序。

宏定义处理特殊字符 -_c语言编译与预处理命令相关推荐

  1. c语言宏定义字符串 换行_C语言换行

    (一) 这几天正在看 ATMEL 的 ARM 处理器 AT91SAM7X256 ,在其官方的头文件中发现有如下宏定义: #define SPI0_PINS (AT91C_PA17_SPI0_MOSI ...

  2. 如何用C语言改变宏定义的大小,C语言中宏定义使用的小细节

    C语言中宏定义使用的小细节 #pragma#pragma 预处理指令详解 在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#p ...

  3. c语言宏定义_掌握C语言,中文编程不是梦

    文/Edward 前面我们在讲节程序编译的时候,编译器做的第一步就是预处理.C语言的预处理,其实是编译器在对整个工程编译之前做的一些文本性质的工作,例如我们经常使用的#include,这就是一个典型的 ...

  4. abs int 宏定义_【C语言】15-预处理指令1-宏定义

    说明:这个C语言专题,是学习iOS开发的前奏.也为了让有面向对象语言开发经验的程序员,能够快速上手C语言.如果你还没有编程经验,或者对C语言.iOS开发不感兴趣,请忽略 预处理指令简介 1.C语言在对 ...

  5. C语言编程宏定义的优缺点,C语言重要知识点总结(二)--内存结构、函数调用过程(栈帧)、宏的优缺点以及##和#的使用...

    一.内存结构 内存大致可以分为四个部分:代码段,静态存储区,堆,栈. 具体划分如下图所示: 栈:在执行函数时,函数内部局部变量的存储单元都可以在栈上创建,函数执行结束后会自动释放内存.栈内存的分配运算 ...

  6. c语言宏定义可变参数,C语言可变参数宏定义方法

    http://blog.csdn.net/skyflying2012/article/details/38436711 2014 在GNU C中,宏可以接受可变数目的参数,就象函数一样,例如: 1 2 ...

  7. c语言用define预处理命令定义,C语言程序设计第八章预处理命令..doc

    一.?选择题1.?对宏命令的处理是_ ___A.?在程序执行时进行的B.?在对程序中其他语句进行编译前进行的C.?在程序连接时进行的D.?与程序中其他语句同时进行编译2.?下面对编译预处理的叙述正确的 ...

  8. abs int 宏定义_在标准C中,预处理语句,特别是宏定义中,常常出现'#'和'##'符号,#字符串创建运算符#...

    我看<U   N   I   X环境高级编程>第七章时看到这么条宏定义: #define   doit(name)   pr_limits(#name,   name) 这里第二个#号是什 ...

  9. c语言有效的预处理命令,9、C语言之预处理命令(示例代码)

    预处理命令 基本概念:ANSI C标准规定可以在C源程序中加入一些"预处理命令",以改进程序设计环境,提高编程效率. 这些预处理命令是由ANSI C同一规定的,但是它们不是C语言本 ...

最新文章

  1. rabbitmq学习——安装测试
  2. R语言聚类分析之基于划分的聚类KMeans实战:基于葡萄酒数据
  3. R语言distCosine函数计算大圆距离实战(Law of Cosines Great Circle Distance)
  4. Linker Tools Error LNK2001 报错
  5. 左神算法:判断 t1 树中是否有与 t2 树拓扑结构完全相同的子树(Java版)
  6. 分布式搜索elasticsearch配置文件详解
  7. 2015年4月27日---C语言:输出特殊图案,请在c环境中运行,看一看,Very Beautiful!...
  8. jenkins运行日志时间与linux,查看日志
  9. 里面的自带的字典在哪里_自带话放的声卡“秘密”
  10. Hive时间戳TIMESTAMP使用的限制
  11. JAVA 基础语法(四)——循环结构(while,do...while,for,break,continue)
  12. Chrome 离线下载最佳方法
  13. 【单片机课程合集】摩尔吧魔鬼集训营,单片机尽情学!
  14. App工程结构搭建:几种常见Android代码架构分析
  15. 【Java+MySQL】随机添加测试数据栗子
  16. 关于Chandrashekhar阿扎德概述
  17. 【Unity】 Unity设置材质的渲染模式(RenderingMode)
  18. matlab分类算法代码,实现几种经典的分类算法(ID3,C4.5等)
  19. 学习大数据,公司常用开发的编程语言是什么?
  20. 新手做无货源店群该如何准确运营?店铺精细化运营对店铺有什么影响?

热门文章

  1. Word2Vec算法详解(相关背景介绍)
  2. IDEA——使用JSONObject时报错怎么办?
  3. java web fileupload_javaweb 文件上传(fileupload) 下载
  4. 星三角正反接线实物图_实物讲解星三角降压启动接线图
  5. 怎么把html背景图片,css如何设置背景图片?
  6. java提取姓名_java获取类型名字的不同方法
  7. linux 二进制安装mysql
  8. 技术面试者的技术深度和广度
  9. DELPHIER,正转向PYTHON了
  10. Debian+Django+uWsgi+nginx+mysql+celery