往期回顾
【第一章】《认识C语言》
【第二章】C语言概述及基本知识1
【第二章】C语言概述及基本知识2
【第三章】字符串和格式化输入/ 输出
【第三章】 printf
【第三章】 scanf
【第三章】 putchar
【第三章】 getchar
【第三章】 sizeof
【第三章】 strlen
文章目录
赋值
#define MAX 1000 //为 MAX,创建一个简短的名字
意思就是给MAX赋值为1000
可以用代码使用宏定义,同样也可以定义数组的大小
#define MAX 1000
#include<stdio.h>
int main()
{
printf("%d\n", MAX);
int arr[MAX];
return 0;
}
我们在编译器中可以看到左边的MAX都被替换成了1000,也就是说在以后的代码中可以用到1000的地方,都可以使用MAX来表示
定义关键字
#define reg register //为 register这个关键字,创建一个简短的名字
如果觉得register太长了,使用不方便,我们还可以创一个简单的名字reg
可以看到 reg被替换成了register。
用更形象的符号来替换一种实现
#define do_forever for(;;)
我们都知道如果for循环中什么条件都没有那就是死循环
所以如果我们想要写出死循环的话也可以使用这种方法
宏定义常量
C 语言中,可以用 #define 定义一个标识符来表示一个常量
//定义常量
#define A 100 //定义整型变量A值为100
#define B "Hello" //定义字符串变量B值为"Hello"(定义字符串需要加双引号)
#define C 3.1415926 //定义浮点数变量C值为3.1415926
凡是以 # 开头的均为预处理指令,预处理又叫预编译。预编译不是编译,而是编译前的处理。这个操作是在正式编译之前由系统自动完成的
定义函数
定义不带参数的函数
#include <stdio.h>
#define A (x*2+5)
int main(void)
{
int x = 2;
printf("A是:%d\n",A);
return 0;
}
/*
A是:9
*/
定义带参数的函数
#include <stdio.h>
#define A(x) (x*2+5)
int main(void)
{
printf("A是:%d\n",A(2));
return 0;
}
/*
A是:9
*/
#include <stdio.h>
#define MAX(a,b) (a>b)?a:b //取两个数最大值
#define MIN(a,b) (a<b)?a:b //取两个数最小值
int main(void)
{
printf("最大值是:%d\n",MAX(5,100));
printf("最小值是:%d\n",MIN(5,100));
return 0;
}
/*
最大值是:100
最小值是:5
*/
define定义函数需注意陷阱
#include <stdio.h>
#define A(x) x*x
int main(void)
{
printf("A是:%d\n",A(2)); //2*2=4
printf("A是:%d\n",A(2+1)); //2+1*2+1=5
return 0;
}
/*
A是:4
A是:5
*/
#include <stdio.h>
#define A(x) (x)*(x)
int main(void)
{
printf("A是:%d\n",A(2)); //(2)*(2)=4
printf("A是:%d\n",A(2+1)); //(2+1)*(2+1)=9
return 0;
}
/*
A是:4
A是:9
*/
#include <stdio.h>
#define A(x) (x)*(x)
int main(void)
{
printf("A是:%d\n",A(2)); //(2)*(2)=4
printf("A是:%d\n",9/A(2+1)); //9/(2+1)*(2+1)=9
return 0;
}
/*
A是:4
A是:9
*/
#include <stdio.h>
#define A(x) ((x)*(x))
int main(void)
{
printf("A是:%d\n",A(2)); //((2)*(2))=4
printf("A是:%d\n",9/A(2+1)); //9/((2+1)*(2+1))=1
return 0;
}
/*
A是:4
A是:1
*/
#include <stdio.h>
#include <string.h>
#define MAX(X,Y) ((X)>(Y)?(X):(Y))
int main()
{
int a=3;
int b=5;
int c=MAX(a++,b++);
//int c=((a++)>(b++)?(a++):(b++));
printf("%d\n",a);
printf("%d\n",b);
printf("%d\n",c);
}
那我们依次对其进行运算,第一次a++结果是4,第一次b++结果是6,第二次a++结果是5,第二次b++结果是7
define替换的规则
最后我们不妨再了解一下#define替换的规则
在程序中扩展#define定义符号和宏时,需要涉及几个步骤。
- 在调用宏时,首先对参数进行检查,看看是否包含任何由#define定义的符号。如果是,它们首先被替换。
- 替换文本随后被插入到程序中原来文本的位置。对于宏,参数名被他们的值所替换。
- 最后,再次对结果文件进行扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上述处理过程。
也就是说#define宏定义会不断地检查我们所使用的地方并且不断地替换宏定义的内容,直到所有内容都被替换完为止。
注意事项
我们在使用**#define定义后不能添加分号**,很多人敲代码时都会习惯性的在后面加上分号,当然这种习惯不能用在宏定义中,使用时请注意
#和##
这个#并不是#define中的#,而是另一种意义的操作符,把一个宏参数变成对应的字符串。
#include <stdio.h>
#include <string.h>
int main()
{
int a=10;
printf("the value of a is %d\n",a);
int b=20;
printf("the value of b is %d\n",b);
float f=3.14f;
printf("the value of a is %f\n",f);
}
可以看到第一种方式是我们平时使用的输出方式,将输出内容放在打印函数的双引号内即可被输出;
那第二种方式也可以用来输出内容,可以将使用双引号引用我们想打印的内容,结果和第一种是相同的,这也是字符串的一个特点。
我们现在知道了这个特征,我们就可以对上面那段冗余的代码进行操作了,直接上代码
#include <stdio.h>
#include <string.h>
#define print_format(num,format) \
printf("the value of "#num" is "format,num)
int main()
{
int a=10;
print_format(a,"%d\n");
int b=20;
print_format(b,"%d\n");
float f=3.14f;
print_format(f,"%f\n");
return 0;
}
##
##可以把位于它两边的符号合成一个符号
int henghengaaa=114514;
#define CAT(x,y) x##y
int main()
{
printf("%d\n",CAT(hengheng,aaa));
return 0;
}
可以看到我们通过#define 的宏定义将字符串的内容连接在了一起,并且成功的输出了我们预期中的结果。
当然我们合成的前提是我们合成的符号必须是可以用的,如果合成出来的字符串没有出现过,那也不能正常使用。