【C语言】宏定义(不带参数的宏定义和带参数的宏定义)

目录

一、不带参数的宏定义

1.定义

2.#undef 指令取消宏定义

二、带参数的宏定义

1.定义

2.宏定义参数替换的注意事项

三、带参数的宏定义和带参函数的区别


一、不带参数的宏定义

1.定义

在程序中,经常会定义一些常量,例如圆周率3.1415、“ABC”等。如果这些常量在程序中频繁使用,难免会出现书写错误的情况。为了避免程序书写错误,可以使用不带参数的宏定义来定义这些常量。

例如:#define PI 3.14159

解析:#define是用来标识一个宏定义,标识符PI是定义的宏名,3.14159是宏体,它可以是常量或表达式等。

一般情况下,宏定义需要放在源程序的开头,函数定义外,它的有效范围是从宏定义语句开始至源文件结束。一般宏名都是大写字母,方便与其他操作符区别。

使用宏定义PI就可以在随后的源代码中出现PI的位置替换为3.14159.

案例演示:

#include <stdio.h>
#define PI 3.141592

int main(){
	int r;
	scanf("%d",&r);
	double area=PI*r*r;
	double cicle=2*PI*r;
	printf("半径为%d的圆面积:area=%lf  周长cicle=%lf\n",r,area,cicle);
} 

 运行结果:

2.#undef 指令取消宏定义

#undef指令用于取消宏定义,当使用#define定义了一个宏之后,如果预处理在接下来的源代码中看到#undef指令,那么#undef指令后面这个宏就会失效。


二、带参数的宏定义

1.定义

带参数的宏定义,其语法格式如下:

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

形参列表中的参数之间用逗号进行分隔。对于带参数的宏定义来说,同样需要使用字符串替换宏名,使用实参替换形参。

由于宏定义在程序预处理的时候执行,因此,相对于函数来说,宏定义的开销要小一些。

【注意】宏定义中的参数替换是“整体替换”。

实例分析:

#define ABS(x)((x)>=0?(X):-(X);

int a=12;

ABS(++a);

我们期望的值是12,但实际a的结果为14,显然这个用来替代求绝对值函数是错误的。

原因是在进行预处理时“ABS(++a)”替换为“(++a)((++a)>=0?(++a):-(++a);”,所以结果为14

案例实现:

#include <stdio.h>
#define SWAP(a,b) {int temp;temp=a;a=b;b=temp;}

int main() {
	int a[5] = { 3,4,5,6,7 };
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5 - i - 1; j++) {
			if (a[j] < a[j + 1])  
				SWAP(a[j], a[j + 1]);
		}
	}

	for (int i = 0; i < 5; i++) {
		printf("%d ", a[i]);
	}
	printf("\n");
}

运行结果:

2.宏定义参数替换的注意事项

  • 若宏定义中字符串出现运算符,需要在合适的位置加上括号,如果不加括号可能会出现错误。

#define S 3+4

a=S*c;//宏定义替换后的语句是a=3+4*c,与期望不符合。

修改为#define S (3+4)

则原语句替换为a=(3+4)*c

  • 宏定义的末尾不用加分号,如果加了分号,将会被视为被替换的字符串的一部分。宏定义只是简单的字符串替换,并不进行语法检查,因此宏替换的错误要等到系统编译时才能被发现。
  • 宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在替换时由预处理程序嵌套替换。但宏定义不支持递归

#define PI 3.14159

#define P PI*x

double c=2*P;宏替换后的语句为c=2*3.14159*x;

宏定义不支持递归

所以#define MAX MAX+5是错误定义方法


三、带参数的宏定义和带参函数的区别

基本操作 带参数的宏定义 带参数的函数
处理时间 预处理期间 程序运行时
参数类型 需要定义的类型
参数传递 不分配空间,无值传递的问题(只是字符串替换) 分配内存,将实参传入形参
运行速度 相对较慢,因为函数的调用会涉及到参数的传递,压栈和出栈等操作

猜你喜欢

转载自blog.csdn.net/Jacky_Feng/article/details/109139444