文/Edward


前面我们在讲节程序编译的时候,编译器做的第一步就是预处理。C语言的预处理,其实是编译器在对整个工程编译之前做的一些文本性质的工作,例如我们经常使用的#include,这就是一个典型的文件包含预处理,当启动编译的时候,编译器首先先做预处理,即将#include后面包含的那个文件里面的内容,全部复制到当前的.c文件中来,接着,再进行C语言源文件的编译。除了文件包含之外,C语言中的预处理还有很多,而这些预处理对于我们编程来说,都可以帮助我们提高代码的易读性和代码质量。


#define预处理

#define预处理的作用,一般在一些书上面仅仅称其为“宏定义”,其实这个称呼是不严谨的,一个#define预处理其实包含两种意思,第一种意思是“宏定义”,第二个层面的意思是替换,下面的内容,我们将会以上面两层意思分开讲解。

#define替换

也许我们在单片机编程中,绝大多数用户使用的仅仅只是#define预处理的替换功能,#define的替换格式为:

#define NAME 需要替换的内容

比如,我们一般常用的用来定义圆周率Π,就可以写成:

#define PI 3.1415926

那么以后的程序代码里面只要出现PI这个标号,编译器都将直接将其替换成一个浮点数3.1415926。

在用#define定义标号的时候需要注意,一般地我们都以大写字母来拼写这个标号,而且这个标号在用#define定义时,我们都默认地将其放入相应的.h头文件中。如图1所示的求圆形面积和周长的程序。

图1 求圆的周长和面积

用#define定义的标号不止可以替换一些数值,还可以替换关键词和函数,例如,想要让C语言变成一个中文的编程语言,就可以直接用#define定义中文标号来替换C语言的关键词,如图2所示。

图2 用中文编写C语言

需要注意的是,MinGW编译器自身不支持中文类型的变量,所以如果要尝试只能在Visual studio软件中使用MSVC来尝试。

#define除了可以替换数值、关键词和函数之外,还可以用来替换程序语句,我们可以将需要执行的程序语句,利用#define重新定义成一个标号,如图3所示。

图3 #define替换程序语句

在图3中,我们利用#define定义了一个程序计算语句,这个标号在程序执行的时候就会自动被替换成后面的2*3运算语句去执行了。接着我们再来看一段代码。如8-1-4所示。

图4 错误的#define替换

按照我们正常的理解,图4中的程序理论上来说应该输出25才对,但是为什么结果却和我们想象的不一样呢?这是因为#define定义的标号在编译的时候是文本直接替换的,因此当在程序里面执行STENCE*STENCE的时候,我们认为的应该执行(2+3)*(2+3),而实际上STENCE是直接被2+3替换的,所以在程序编译时的真实替换应该是2+3*2+3,因此输出的值才和我们想象中的不一样,这就是典型的#define替换错误。只需要在2+3外面加上括号即可,如图5所示。

图5 正确的#define程序语句替换

而当我们在替换多条语句的时候,一定要用“do{……}while(0);“的形式来将标号里面的多条执行语句打包好,以防止不必要的错误产生。如图6所示。

图6 #define替换多条程序语句

定义宏

#define除了用作简单和复杂的程序文本替换之外,这个机制还包括了一个规定,即可以将参数替换到文本中去进行计算,这种实现通常被称为宏(macro)。

宏定义的声明方式为:

#define 宏名称(参数1, 参数2, ……) 带参数的表达式

当宏被调用时,参数列表中的每一个值都会与宏表达式实体中的每一个值所一一对应,并且进行替换。如,我们定义一个用于计算平方的宏,就可以写成:

#define SQUARE(x) x*x

下面程序使用宏定义计算5的平方,就可以直接使用SQUARE(5)。

如图7所示,我们可以将圆的面积和周长计算分别写成宏的形式进行运算。

图7 宏定义计算圆的周长和面积

但是还需要注意的是,宏定义的参数替换也仅仅是文本形式的替换,如图8所示。

图8 宏定义的错误计算

图8的程序中,我们原本想的是,输入的半径变成11之后,通过调用宏,并且传入参数rad + 1,理论上来说应该和8-1-7中输出一样的计算结果才对,但是实际上,这个传入的参数在替换时也是仅仅被当作文本去替换了,因此图8程序实际的计算过程应该是,以周长为例,2*3.1415926*11+1=70.12。所以在宏定义的时候,我们也应该为其参数增加括号,以提高整个宏的完整性。如图9所示。

图9 宏定义参数的正常使用

除了上述的功能之外,宏定义最常被使用的就是比较两个数的大小了,之前我们比较两个书的大小都是使用if来判断的,但是学了宏之后,结合三目运算符就可以直接使用一个宏定义来完成了,如图10所示。

图10 使用宏定义比较大小

http://weixin.qq.com/r/BjsfB7PEhO77rfdk924U (二维码自动识别)

c语言宏定义_掌握C语言,中文编程不是梦相关推荐

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

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

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

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

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

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

  4. c语言 宏定义 去除宏定义_如何检查是否在C中定义了宏?

    c语言 宏定义 去除宏定义 To check whether a Macro is defined or not in C language – we use #ifdef preprocessor ...

  5. c语言中#39;xd#39;代表什么,关于C语言宏定义的技巧:#39;##39;和#39;###39;

    关于C语言宏定义的技巧:'#'和'##' '#'和'##' '#'和'##'是两个预处理运算符,只能在预处理的过程中使用.在带参数的宏定义中, '#'运算符后面应该跟一个参数,预处理器会把这个参数转换 ...

  6. 转载--c语言宏定义(1)

    作者:独舞风 链接:c语言宏定义(1) 1.为什么要有宏定义? 代码中某个特定数值需要参与运算,而且该数值作用于多个地方,当需要对该数值进行修改时,希望只改动一个地方就能实现该数值的全部更新:即便某个 ...

  7. C/C++语言宏定义##连接符和符#的使用

    C/C++语言宏定义##连接符和符#的使用     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/53113187 (一) ...

  8. c语言宏定义技巧和用法,关于C语言宏定义的技巧:'#'和'##'

    关于C语言宏定义的技巧:'#'和'##' '#'和'##' '#'和'##'是两个预处理运算符,只能在预处理的过程中使用.在带参数的宏定义中, '#'运算符后面应该跟一个参数,预处理器会把这个参数转换 ...

  9. 51单片机c语言宏定义是什么意思,51单片机的C语言宏定义应用.doc

    1.预编译处理是单片机C语言程序设计中经常用到的一种方法.通过一些预处理命令可以为C语言本身提供许多功能和符号的扩充,增强C语言程序的灵活性和方便性. 常用的预处理命令有:宏定义.文件包含.条件编译等 ...

最新文章

  1. 人脸检测--S3FD: Single Shot Scale-invariant Face Detector
  2. CentOS7 安装 mysql8
  3. Spring+Ibatis集成开发实例
  4. java中取得上下文路径的方法
  5. Java数三退一问题代码_数三退一问题算法(Java)
  6. 【HTML5初探之绘制图像(上)】看我canvas元素引领下一代web页面
  7. php正则过滤html标签_空格_换行符的代码,PHP 正则过滤 html 标签、空格、换行符的代码 (文章格式化)...
  8. 程序员的创业困境 谁来帮助出出主意?
  9. boost库下的deadline_timer和steady_timer 区别
  10. MFC无法使用CDialogEx类
  11. Linux修改后保存与不保存,强制退出vi与vi下查找命令关键步骤!
  12. max日期最大值为0_【SQL】SQL面试50题思路解答与分类整理(下)CASE与日期函数...
  13. Elasticsearch海量搜索引擎
  14. 传感器系列(一)——超声波测距传感器 HC—SR04模块
  15. Apple 宣布 2021 年 Apple Design Awards 获奖者
  16. win10怎么更新显卡驱动_荒野大镖客2优化:NVIDIA更新GeForce 441.41显卡驱动
  17. verilog分频电路
  18. Opencv中,imag=cv2.cvtColor(imag,cv2.COLOR_BGR2GRAY) 报错:error:!_src.empty() in function ‘cv::cvtColor‘
  19. 「开发者说」多系统集成开发-企业自有系统快速上钉钉
  20. Android 语音播报 , 百度在线语音合成封装;

热门文章

  1. 第二阶段冲刺第六天(6月5号)
  2. 黑马程序员_Java面向对象_包
  3. PHP pear安装
  4. HDU 3874 Necklace (数状数组)
  5. APL开发日志 -- 2013-03-02
  6. 人大经济论坛:统计学的一些经典教材
  7. android 相册 uri空,android拍照获得图片URI为空的处理方法
  8. android 模拟器识别,一种基于符号的识别Android应用运行在模拟器中的方法与流程...
  9. vue 分模块打包 脚手架_vue-cli分模块独立打包
  10. 016_Servlet上下文