目录
1.预定义符号
__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义注意:单词的左右各有两个下划线
STDC的全称:Standard C
打印预定义符号的值
由于VS2022不严格遵循ANSI C,因此默认不启用__STDC__宏
可以在VS2022的项目-->属性-->配置属性-->C/C++-->命令行中添加/Zc:__STDC__
来启用__STDC__宏
#include <stdio.h>
int main()
{
printf("__FILE__:%s\n,__LINE__:%d\n__DATE__:%s\n__TIME__:%s\n__STDC__:%d",__FILE__,__LINE__,__DATE__,__TIME__,__STDC__);
return 0;
}
在预处理阶段,会将__FILE__,__LINE__,__TIME__,__STDC__替换为相应的数据
运行结果
2.#define的用法
1.定义常量
格式:#define 名字 要替换为的内容
如#define ROW 9(此为定义符号常量)和平常给变量赋值(int ROW = 9;)有所不同,编译器对前者的处理的策略为:将函数中ROW全部替换为9,而对后者对ROW赋值为9,变量在内存中有存储空间
如#define reg register,为 register这个关键字起一个短的名字
#define do_forever for(;;),将代码中的do_forever替换为for(;;),显然是死循环
#include <stdio.h>
#define do_forever for(;;)
int main()
{
do_forever
printf("循环");
return 0;
}
#define CASE break;case,将代码中的CASE替换为break;case
#include <stdio.h>
#define CASE break;case
int main()
{
switch (1)
{
case 1:
CASE 2 :
CASE 3 :
CASE 4 : ;
}
return 0;
}
预处理后变为
switch (1)
{
case 1:
break; case 2 :
break; case 3 :
break; case 4 : ;
}
#define test printf("Hello World!")将代码中的test替换为printf("Hello World!")
#include <stdio.h>
#define test printf("Hello World!")
int main()
{
test;
return 0;
}
预处理后变为
int main()
{
printf("Hello World!");
return 0;
}
注意:不建议在#define的最后加;可能会导致编译问题
2.定义宏
允许把参数替换到文本中称为定义宏(macro)
格式:#define MACRO_NAME(ARG1, ARG2,..) (expression within brackets)
注:第二个括号有时可以省略,如果出现优先级的问题,建议不要省略
代码示例
#include <stdio.h>
#define ADD(a,b) a+b
int main()
{
int a = 2;
int b = 3;
int ret = ADD(a, b);
printf("%d", ret);
return 0;
}
定义宏ADD,注意:ADD和(a,b)不能分开写,否则编译器会认为将ADD替换为(a,b) a+b
运行结果
深刻理解替换的本质
求下列代码运行的结果
#include <stdio.h>
#define DOUBLE(x) 2*x
int main()
{
int a = 2;
int ret = DOUBLE(a+1);
printf("%d", ret);
return 0;
}
错误答案:9
正确答案:5
DOUBLE(a+1)在预处理阶段被替换为2*a+1,*的优先级比+大
因此应该使用括号来解决优先级问题 写成#define DOUBLE(x) 2*(x)