C语言 预处理指令和宏定义

目录

一、预定义符号

二、预处理指令 #define

1.#define 定义标识符

2.#define 定义宏

3.#define 替换规则

三、预处理操作符 # 和 ##

1.预处理操作符 #

2.预处理操作符 ##

四、带副作用的宏参数

五、宏和函数的对比 

1.宏的优点:

2.宏的缺点:

六、条件编译

1.条件编译作用

2.条件编译方法

2.1 单分支 #if 常量表达式(判断常量表达式真假)

2.2 多分支 #if 常量表达式(判断常量表达式真假)

2.3 判断是否被定义

2.4 嵌套指令


一、预定义符号

__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义;

//预定义符号都是语言内置的;

#include <stdio.h>
int main()
{
	printf("%s\n", __FILE__);
	printf("%d\n", __LINE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
	//printf("%d\n", __STDC__);//VS未遵循ANSI C,未定义__STDC__;
	return 0;
}

二、预处理指令 #define

1.#define 定义标识符

//语法:#define name stuff

#include <stdio.h>
#define MAX 1000 //定义整型,字符串等;
#define reg register //为关键字register,创建一个简短的名字;
#define do_foreber for(;;) //用更形象的符号来替换一种实现;
#define CASE break;case //在写case语句时,自动将break加上;//不建议该写法;
//如果定义的 stuff 过长,可以分成几行写,除了最后一行外,每行的后面都加上一个反斜杠(续航符)。
#define DEBUG_PRINT printf("file:%s\nline:%d\ndate:%s\ntime:%s\n",\
				__FILE__, __LINE__, \
				__DATE__, __TIME__)
//注意 #define 语句末尾不要加 ";" 号;
int main()
{
	int m = MAX;
	DEBUG_PRINT;
	printf("%d\n", MAX);//输出:1000 ;
	return 0;
}

2.#define 定义宏

        #define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro);

//宏的申明方式:#define name(parament-list) stuff

        其中的 parament-list 是一个由逗号隔开的符号表,他们可能出现在 stuff 中;

        参数列表的左括号必须与name紧邻;如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分;

#define SQUARE(X) ((X)*(X))//注意添加括号,以明确运算顺序;
#define DOUBLE(X) ((X)+(X))
int main()
{
	int r = SQUARE(5 + 1);
	//int r = ((5 + 1) * (5 + 1));//替换SQUARE得到;
	printf("%d\n", r);//输出36;

	int n = 10 * DOUBLE(3);
	//int r = 10 * ((3) + (3));//替换DOUBLE得到;
	printf("%d\n", n);//输出60;
	return 0;
}

//注意:用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用;

3.#define 替换规则

//在程序中扩展#define定义符号和宏时,需要涉及几个步骤;

        1.在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,则首先被替换;

        2.替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换;

        3.最后再次对结果文件进行扫描,看看是否包含任何由#define定义的符号。如果仍包含,则重复上述处理过程;

        注意:宏参数和#define定义中可以出现其他#define定义的符号,但对于宏,不能出现递归;当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索;

三、预处理操作符 # 和 ##

1.预处理操作符 #

        在预处理操作符 # 后跟随输入变量,相当于将这个变量转换为字符串;

#define PRINT(N) printf("the value of "#N" is %d\n",N)//#N 的 # 相当于将 N 转换为了字符串;
#define OPRINT(N,FORMAT) printf("the value of "#N" is "FORMAT"\n",N)
int main()
{
	//以下语句输出一致;
	printf("hello world\n");
	printf("hello " "world\n");
	
	int a = 10;
	int b = 20;
	float f = 3.14f;
	//不使用宏,让语句根据传入变量名的改变而改变输出的目的;
	printf("the value of a is %d\n", a);
	printf("the value of b is %d\n", b);
	//使用同一个宏,达到让语句根据传入变量名的改变而改变输出的目的;
	PRINT(a);
	PRINT(b);
	//使用同一个宏,达到让语句根据传入变量名和数据类型的改变而改变输出的目的;
	OPRINT(a, "%d");
	OPRINT(f, "%.2lf");
	return 0;
}

2.预处理操作符 ##

        预处理操作符 ## 可以将位于它两边的符号合成一个符号;它允许宏定义从分离的文本片段创建标识符;

#define CAT(class,Num) Class##Num
// ## 两边的符号会合并形成一个符号;这样的连接必须产生一个合法的标识符,否则其结果为未定义;
int main()
{
	int Class106 = 100;
	printf("%d\n", CAT(Class, 106));//将Class和106分别作为符号传输到宏CAT中,此时两个符号合并为Class106,输出:100;
	return 0;
}

四、带副作用的宏参数

#define MAX(x,y) ((x)>(y)?(x):(y))
int main()
{
	int a = 5,b = 4;
	int m = MAX(a++, b++);
	printf("m=%d ", m);//输出:6
	printf("a=%d b=%d\n", a, b);//输出:7,5
	//在传入参数,计算MAX时,表达式计算中断跳出后,中断之后的代码不再执行,参数的自增出现问题;
	return 0;
}

        //当宏参数在宏的定义中出现超过一次的时候,如果参数带有副作用,那么在使用这个宏的时候就可能出现危险,导致不可预测的后果。副作用就是表达式求值的时候出现的永久性效果;

五、宏和函数的对比 

//宏通常被应用于执行简单的运算,这是由宏的优缺点决定的;

1.宏的优点:

        (1)由于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多,所以宏比函数在程序规模和速度方面更胜一筹;

        (2)函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用,而宏的使用是和数据类型无关的;

2.宏的缺点:

        (1)每次使用宏的时候,一份宏定义的代码将插入到程序中,除非宏的代码量较小,否则可能大幅度增加程序长度;

        (2)宏无法调试,无法递归;

        (3)宏与类型无关,因此不够严谨;

        (4)宏可能会带来运算符优先级的问题,容易导致程序出错;

六、条件编译

1.条件编译作用

//使用条件编译指令,在编译一个程序的时候,可以将一条(或一组)语句编译或者放弃;

2.条件编译方法

2.1 单分支 #if 常量表达式(判断常量表达式真假)

#if 常量表达式
#endif

#include <stdio.h>
#define CHECK 1
int main()
{
#if CHECK==1
	printf("true\n");//输出:true;
#endif

#if CHECK==0
	printf("false\n");//不输出;
#endif
	return 0;
}

2.2 多分支 #if 常量表达式(判断常量表达式真假)

#if 常量表达式
#elif 常量表达式
#else
#endif

#include <stdio.h>
#define CHECK 0
int main()
{
#if CHECK
	printf("CHECK != 0\n");//不输出;
#elif 1==2 
	printf("false\n");//不输出;
#else 
	printf("CHECK == 0\n");//输出:CHECK == 0;
#endif
	return 0;
}

2.3 判断是否被定义

//3.1如果有定义
#if defined(符号)
#ifdef 符号
//3.2如果无定义
#if !defined(符号)
#ifndef 符号

#include <stdio.h>
#define CHECK 1
int main()
{
#ifdef CHECK
	printf("ture\n");//输出:ture;
#endif

#if defined(ture)
	printf("CHECK\n");//不输出;
#endif

#if !defined(CHECK)
	printf("ture\n");//不输出;
#endif

#ifndef ture
	printf("CHECK\n");输出:CHECK;
#endif
	return 0;
}

2.4 嵌套指令

#if defined(符号)
       #ifdef 符号
              执行语句;
       #endif
#ifdef 符号
              执行语句;
       #endif
#elif defined(符号)
       #ifdef 符号
              执行语句;
       #endif
#endif

#include <stdio.h>
#define MAX 100//定义 MAX ;
#define MIN 0//定义 MIN ;
int main()
{
#if defined(MAX)
	#ifndef MIN
		printf("false\n");//不输出;
	#endif
	#if MAX!=0
		printf("MAX != 0\n");//输出:MAX != 0;
	#endif
#elif !defined(MAX)
	#ifdef MIN==0
		printf("MIN == 0\n");//不输出;
	#endif
#endif
	return 0;
}

(-- end --)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值