1. 预定义符号
预定义符号主要有以下几种:
符号 | 含义 |
---|---|
__FILE__ | 源文件所在位置(绝对路径) |
__LINE__ | 所在的行号 |
__DATE__ | 文件被编译时的日期 |
__TIME__ | 文件被编译时的时间 |
__STDC__ | 若编译器遵循ANSIC,则为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__); //若编译器遵循ANSIC,则为1,否则未定义
return 0;
}
运行结果:
E:\C\Project1\Project1\project1.c
5
Jan 11 2024
10:00:58
2. #define
#define 可以用来定义常量,也可以用来定义宏。
2.1 定义常量
定义标识符的操作很简单:
#include<stdio.h>
#define XX 100
int main()
{
printf("%d\n", XX); //输出结果就为100
return 0;
}
2.2 定义宏
允许把参数替换到文本中,这种实现通常称为宏或定义宏。
#define name( parament-list ) stuff
#include<stdio.h>
#define MULTIPLY(m) m*m
int main()
{
int x = 8;
printf("%d\n", MULTIPLY(x)); //等同于 x*x ,结果为 64
printf("%d\n", MULTIPLY(x+2)); //等同于 x+2*x+2,结果为 26
printf("%d\n", 3*MULTIPLY(x+2)); //等同于 3*x+2*x+2,结果为 42
return 0;
}
运行结果:
64
26
42
可以看出,最后的结果和想象的结果有些区别,所以为了保证结果的准确,通常会在定义宏的时候尽可能多加括号。以上列代码为例,
#define MULTIPLY(m) ((m)*(m))
这样就避免了因缺少括号出现的计算错误。
3. # 和 ##
以下是未使用 # 的代码及运行结果。
#include<stdio.h>
#define PRINT(x,num) printf("the word x is "num"\n",x)
int main()
{
int a = 100;
PRINT(a, "%d");
float b = 2.5;
PRINT(b, "%f");
return 0;
}
运行结果:
the word x is 100
the word x is 2.500000
3.1 #运算符
#
运算符会把宏的参数转换为字符串。
#include<stdio.h>
#define PRINT(x,num) printf("the word " #x " is "num"\n",x)
int main()
{
int a = 100;
PRINT(a, "%d");
float b = 2.5;
PRINT(b, "%f");
return 0;
}
运行结果:
the word a is 100
the word b is 2.500000
从结果可以看出由原来固定不变的 x 变成了可改变的参数。
3.2 ##运算符
##
的作用是把两边的符号连接起来变成一个符号,使用该符号也要确保合成的是一个合法的符号, ##
也被称为记号粘合。
4. 宏的命名
我们知道宏和函数的使用方法是极其相似的,所以为了区分二者,通常宏名是全部大写的。
5. #undef
#undef 的作用是取消以前定义的宏定义。
#include<stdio.h>
#define X 100 //宏定义
int main()
{
printf("%d", X); //输出100
#undef X //取消宏定义
printf("%d", X); //这里的 X 就变成未定义的标识符
return 0;
}