C语言编译预处理详细易懂版

C语言允许在源程序中包含编译预处理命令,他们以"#"开头,包括宏定义、文件包含和条件编译。本博客主要详细介绍宏定义、文件包含和条件编译。


目录

一、宏定义

1、无参数的宏定义

2.带参数的宏定义

3.函数与宏定义的区别

二、文件包含

三、条件编译

1. #ifdef...#else...#endif

2.#ifndef...#else...#endif

3.#if...#else...#endif

4.#if...#elif...#endif


一、宏定义

1、无参数的宏定义

是指用一个指定的标识符来代表一个字符串,一般格式如下:

#define  宏名  字符串

说明:①#表示预处理命令,在C语言中以“#”开头的均为预处理命令。
②define表示宏定义命令。
③宏名常用大写字母表示,这样易于区别程序中的宏名和普通变量名。
④字符串表示宏的内容文本,也称为宏体,是一个ASCII 码的字符序列,可以是常
数、表达式、格式串等。 

注意:(1)宏定义是用宏名替换一个字符串,即原样替换,不做语法检查。如有错误,
只能在展开后编译源程序时才被发现。
(2)宏定义不是C语句,在行末不必加分号,如果加上分号则连分号也一起替换。

#define PI 3.14;
//则语句“area=PI*R*R;"宏扩展为"area=3.14;*R*R;",编译时将出现语法错误


(3)宏名在源程序中若用引号括起来,则预处理时不对其进行宏替换。例如:

//语句"printf("PI");的输出结果为字符串PI而不是前面所定义的值


(4)宏定义必须写在函数之外,其作用域为从宏定义开始到源程序末尾结束。若要终止其作用域可以用#undef命令。

(5)宏定义允许嵌套,即可以引用已定义的宏名,层层置换。
(6)宏定又是预处理命令,它与变量的含义不同,不分配内存空间,只做字符替换。


2.带参数的宏定义

是指宏名后面带有参数。在编译预处理时,不仅要对宏名进行字符串替换,还要对参数进行替换。宏定义中的参数称为形式参数(简称形参),宏调用中的参数称为
实际参数(简称实参),这点与函数有此相似。带參数的宏定义的一般格式为:

#define 宏名(形参列表)  字符串


说明:
①宏名和括号之间不能有空格,否则将空格以后的字符串均作为替换的字符串。
例如,有如下宏定义:

#define MAX (a,b) (a>b)? (a): (b)
//则MAX被当作无参数宏的宏名,“(a,b) (a>b)? (a): (b)"为要替换的字符串。


②形参列表由个或多个参数构成,参数只有参数名,没有数据类型说明符,参数
之间用逗号隔开,参数名必须是合法的标识符。


在处理带参数的宏时,预处理程序首先将宏的内容文本中的形参替换成实参,这样就形成
宏的实际内容文本,然后再用宏的实际内容文本替换源程序中的宏名。带参数的宏调用的一
最格式如下:


宏名(实参列表)


说明:
①实参列表由一个或多个参数构成,与宏的形参列表一一对应 ,实参可以是常量、
变量或表达式,参数之间用逗号隔开。
②带参数的宏在使用时,若参数为表达式,应将宏参数用“( )”括起来。例如,有
如下宏定义:
 

#define SQRT(a) a*a

3.函数与宏定义的区别

(1)宏定义中形参不分配存储空间,因此不必进行数据类型说明;而函数在调用时要为
参分配临时的存储空间,因此形参需要进行数据类型说明。
(2) 函数调用时,先计算实参表达式的值,然后再将其传递给对应的形参;而带参数的工
定义则对实参表达式不做计算而是将字符串进行原样替换。
(3)丽数通过函数名只能返回一个计算结果; 而宏定义可以得到多个计算结果。

二、文件包含

文件包含是指一个源文件可以将另个源 文件的内容包含进来。一般格式如下


linclude <文件名>

include“文件名"


文件包含#include命令的预处理就是将被包含的文件的内容插人源程序中,如图:


说明:
①文件包含命令可以使用尖括号“< >”和双引号" "
这两种形式的区别在于:
使用双引号则表示首先在源文件当前目录中查找,若未找到才到存放C库函数头文件
所在的目录中查找。使用尖括号表示在存放C库函数头文件所在的目录中查找(由用
户在设置编译环境时进行设置)。
②一个include 命令只能指定一个被包含文件,若有多个文件包含,则用多个include命令。
③文件包含允许嵌套。 

三、条件编译

1. #ifdef...#else...#endif

语法格式如下: 


#ifdef  宏名
程序段1
#else
程序段2
#endif


功能:如果”宏名”已经用#define命令定义过,则编译“程序段1”;否则编译”程序段2”。
说明:①如果没有“程序段2”,则本格式中的#else部分可以没有,但#endif必须存在,即
可以写成:

#ifdef  宏名
程序段1
#endif


②"#ifdef   宏名”的含义是判断是否定义了宏。

2.#ifndef...#else...#endif

#ifndef  宏名

         程序段1

#else

         程序段2

#endif

功能:如果宏名没有用define命令定义过则编译“程序段1”,否则编译“程序段2,刚好与第一种格式的功能相反。
例如:

#ifndef A
      a=32;
#else
      a=16;
#endef
//上述条件编译命令表示,如果宏名A没有用#define定义过,则编译“a=32",否则编译“a=16”。

3.#if...#else...#endif


#if 常量表达式

             程序段1

#else

            程序段2

#endif

功能:如果常量表达式的值为真(非0)则编译“程序段1”否则编译程序段2。
说明:1.常量表达式中不能包含变量名,通常会用到宏名,可以不加括号()

2.如果没有程序段2则本格式中的#else部分可以省略,但#endif必须存在。

4.#if...#elif...#endif

#if  常量表达式1

          程序段1

#elif   常量表达式2

          程序段2

#else

          程序段3

#endif

功能:如果常量表达式1的值为真(非0)则编译程序段1,否则判断常量表达式2,如果值为真(非0)则编译程序段2,否则编译程序段3。 


本期博客到这里结束啦~如果对你有用的话点个赞收藏吧! 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值