宏定义
1、预处理符号
注意:DATE 和TIME在C语言中是用来记录编译的系统日期和时间的,用起来简单,但是很有作用。在共同开发时,通过上段代码的打印,可以判断代码是什么时间发布的,便于版本的甄别,有效避免因版本问题引起的错误。 并不能用来表示当前运行到这一步的时间。
[root@ubuntu0006:/media/hankin/vdb/TransferStation] #./a.out
study_define.cpp
1
10
main
Jun 30 2022
09:16:45
[root@ubuntu0006:/media/hankin/vdb/TransferStation] #date
2022年 06月 30日 星期四 09:19:09 CST
__FILE__ :进行编译的源文件名字
__LINE__ :文件当前行的行号
__DATE__ :文件被编译的日期
__TIME__ :文件被编译的时间
__STDC__ :如果编译器遵循ANSIC,其值就为1,否则未定义
__FUNCTION__:当前的函数名
2、示例
#include <iostream>
#include <cstring>
using namespace std;
//刚好__FILE__也是类似string的字符串,所以不加双引号的时候相当于赋值
string strs[] = {__FILE__, "__LINE__", "__DATE__", "__TIME__", "__STDC__"};
int main()
{
for (int i = 0; i < 5; i++) {
cout << strs[i] << endl;
}
cout << __FILE__ << endl;
return 0;
}
/*
study_define.cpp
__LINE__
__DATE__
__TIME__
__STDC__
study_define.cpp
*/
c++的输出有个好处就是不用指定数据的格式
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int main()
{
printf("%s\n", __FILE__);
cout << __STDC__ << endl;
cout << __LINE__ << endl;
cout << __FUNCTION__ << endl;
cout << __DATE__ << endl;
cout << __TIME__ << endl;
return 0;
}
/*
study_define.cpp
1
10
main
Jun 30 2022
09:16:45
*/
3、详解
宏的声明方式:
#define name(para_list) stuff
注意:name和左括号之间不能有空格;
3-1、需要注意的几点
1.所有用于对数值表达式进行求值的宏定义都应该多加括号;
以下错误代码:
#define SQUARE(x) x*x
SQUARE(5)
SQUARE(a+1)
应该修改为:
#define SQUARE(x) ((x)*(x))
SQUARE(5)
SQUARE(a+1)
2.如果宏定义中的语句非常长,那么可以写成多行,除了最后一行之外,每行的末尾都要加一个反斜杠 “ \ ”
#define DEBUG_PRINT printf("FILE %s line %d:" \
"x=%d,y=%d,z=%d"\
__FILE__,__LINE__,\
x,y,z)
3.在程序中使用到#define定义的宏时,将被插入到程序中原来文本的位置;
4.参数名将被他们的值所代替; (1) 邻近字符串自动连接:
#include <stdio.h>
#define PRINT(FORMAT, VALUE) printf("The value is " FORMAT "\n", VALUE)
int main(void)
{
PRINT("%d", 12);
return 0;
}
/*
The value is 12
*/
(2) 预处理器把一个宏参数转换成一个字符串:#argument 这种结构被预处理器翻译为字符串 “argument”
#include <stdio.h>
#define PRINTF(FORMAT,VALUE) printf("The value "#VALUE" is " #FORMAT "\n",VALUE)
int main(void)
{
PRINTF(%d,20);
return 0;
}
/*
The value 20 is 20
*/
(3) 使用##结构,将位于其两边的符号连接成一个符号;
#include <stdio.h>
#define ADD_TO_SUM(SUM_NUMBER, VALUE) sum ## SUM_NUMBER += VALUE
int main(void)
{
int sum5 = 0;
ADD_TO_SUM(5, 25); // 相当于是sum5 += 25
printf("%d.\n", sum5);
return 0;
}
/*
25.
*/
(4) 带副作用的宏参数 当宏参数在宏定义中出现次数超过一次时,那么将可能出现副作用;
#include <stdio.h>
#define MAX(a,b) ((a)>(b)?(a):(b))
int main()
{
int x = 5;
int y = 8;
int z = 0;
z = MAX(x++, y++); // z = ((x++)>(y++)?(x++):(y++))
printf("x = %d, y = %d, z = %d\n", x, y, z); // 6 10 9
return 0;
}
5.宏命名 一般约定使用大写;与函数区分开;
6.#undef 本指令用于移除一个宏定义;
#include <stdio.h>
#ifndef MAXN
#define MAXN 2005
#endif
#undef MINN
#undef MAXN
int main()
{
printf("MAXN = %d\n", MAXN);
return 0;
}
/*
pointer_free.cpp: In function ‘int main()’:
pointer_free.cpp:12:24: error: ‘MAXN’ was not declared in this scope
printf("MAXN = %d\n", MAXN);
^
*/
如果现存的名字需要被重新定义,那么旧定义首先必须用#undef移除;
4、如何在函数动态运行时获取宏定义的宏的名字
//可以输出变量名
#define get_marco_name(x) #x
#define get_name(x) #x
详情见:D:\Github\Storage\c++\standard_library\define\define.c
注意:不能直接在程序中使用#号输出变量名。