C\C++中的预处理

一、预处理功能:

预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译、布局控制和宏替换4种。

  • 文件包含:#include 是一种最为常见的预处理,主要是做为文件的引用组合源程序正文。
  • 条件编译:#if,#ifndef,#ifdef,#endif,#undef等也是比较常见的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
  • 布局控制:#progma,这也是我们应用预处理的一个重要方面,主要功能是为编译程序提供非常规的控制流信息。
  • 宏替换: #define,这是最常见的用法,它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。

 

二、预处理指令:

预处理指令的格式如下:

#directive tokens

#符号应该是这一行的第一个非空字符,一般我们把它放在起始位置。如果指令一行放不下,可以通过/进行控制,例如:

#define Error if(error) exit(1) 等价于

#defineError /

if(error)exit(1)

 

常见的预处理指令:

#define 宏定义

#undef 未定义宏

#include 文本包含

#ifdef 如果宏被定义就进行编译

#ifndef 如果宏未被定义就进行编译

#endif 结束编译块的控制

#if 表达式非零就对代码进行编译

#else 作为其他预处理的剩余选项进行编译

#elif 这是一种#else和#if的组合选项

#line 改变当前的行数和文件名称

#error 输出一个错误信息

#pragma 为编译程序提供非常规的控制流信息

 

三、文件包含指令:

这种预处理使用方式是最为常见的,平时我们编写程序都会用到,最常见的用法是:

#include <iostream> file://标准库头文件

#include "IO.h" file://用户自定义的头文件

 

注意点:

<io.h>和"io.h"的区别

对于#include<io.h> ,编译器从标准库路径开始搜索

对于#include"io.h" ,编译器从用户的工作路径开始搜索

四、编译控制指令(条件编译):

这些指令的主要目的是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。

使用格式,如下:

 

 

1、

#ifdef   identifier

    your code

#endif

如果identifier为一个定义了的符号,your code就会被编译,否则剔除

2、

#ifnde   fidentifier

    your code

#endif

如果identifier为一个未定义的符号,your code就会被编译,否则剔除

3、

#ifexpression

     your code

#endif

如果expression非零,your code就会被编译,否则剔除

4、

#ifdef  identifier

    your code1

#else

     your code2

#endif

如果identifier为一个定义了的符号,your code1就会被编译,否则your code2就会被编译

5、

#ifexpressin1

     your code1

#elifexpression2

     your code2

#else

     your code3

#enif

如果epression1非零,就编译your code1,否则,如果expression2非零,就编译your code2,否则,就编译your code3

 

防止头文件重复编译:

#ifndef _FILE_NAME_H_

#define _FILE_NAME_H_

/* code */

#endif // #ifndef _FILE_NAME_H_

用条件编译来注释代码,

#if 0

/* comment ...

*/

// code

/* comment */

#endif

 

定义常量

#ifndef NULL

#define NULL (void *)0

#endif // #ifndef NULL

 

五、其他预编译指令

除了上面我们说的集中常用的编译指令,还有3种不太常见的编译指令:#line、#error、#pragma,我们接下来就简单的谈一下。

(1)#line

语法:

#line number filename

例如:#line30 a.h 其中,文件名a.h可以省略不写。

这条指令可以改变当前的行号和文件名,例如上面的这条预处理指令就可以改变当前的行号为30,文件名是a.h。初看起来似乎没有什么用,不过,他还是有点用的,那就是用在编译器的编写中,我们知道编译器对C++源码编译过程中会产生一些中间文件,通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析。

(2)#error

语法:

#error info

在预处理阶段,如果出现了错误,则#error指令可以生成一个诊断消息,并显示为一个编译错误,同时中止编译

#ifndef __cplusplus

#error "Error - Should be C++"

#endif

 

(4)#pragma

#pragma是非统一的,他要依靠各个编译器生产者,编译器未识别出来的#pragma指令都会被忽略。

 

例如,在SUNC++编译器中:

// 把name和val的起始地址调整为8个字节的倍数

#progmaalign 8 (name, val)

charname[9];

doubleval;

//在程序执行开始,调用函数MyFunction

#progmainit (MyFunction)

 

六、预定义标识符

为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但是他们都会处理下面的4种:

__FILE__前源文件中的代码行号,十进制整数

__LINE__ 当前源文件中的代码行号,十进制整数

__DATE__ 源文件的处理日期,字符串字面量,格式mmm ddyyyy其中mmm是月份如Jan、Feb等 dd是01-31 yyyy是四位的年份

__TIME__ 源文件的编译时间,也是字符串字面量格式是hh:mm:ss

__STDC__ 这取决于实现方式,如果编译器选项设置为编译标准的C代码,通常就定义它,否则就不定义它

__cplusplus 在编译C++程序时,它就定义为199711L

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值