C++宏定义

1、#define命令

#define命令时C语言中的一个宏定义命令,它将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串被称为替换文本。

1.1 不带参数的宏定义

格式:#define 标识符  字符串

例如:

#define PI 3.1415926

宏定义的功能在于预处理(预编译):将宏名替换为字符串。

说明:

  • 宏名一般要大写
  • 使用宏可提高程序的可读性,减少不一致性,减少输入错误和便于修改。例如:数组大小通常用宏定义
  • 预处理时在编译之前的处理,而编译的工作任务之一就是检查语法,预处理不做语法检查
  • 宏定义末尾不加分号
  • 宏定义写在函数花括号外,并且在文件的最开头
  • 可以用#undef命令终止宏定义的作用域
  • 宏定义可以嵌套

1.2 带参数的宏定义

格式:#define 标识符(参数表) 宏体

例如:

#define N(x,y) x*y

若在程序中出现代码“area=N(3,3);” 则执行顺序为:先替换为“area=x*y;”,再替换为“area=3*3;”

说明:

  • 实参如果是表达式容易出问题,例如:#define S(r) r*r        代码:area=S(a+b); 执行顺序:1.area=r*r   2.area=a+b*a+b   所以正确的宏定义为:#define S(r) ((r)*(r))
  • 宏名和参数的括号之间不能有空格
  • 宏替换只做替换,不做计算,也不做表达式求解
  • 宏展开不占运行时间,只占用编译时间

下面继续看两个例子:

#define MAX(a,b) ((a)>(b)?(a):(b))
...
i_max = MAX(1+2,value);

替换成:((1+2)>(value)?(1+2):(value))

#define FUCT(a) "a"
...
str = FUCT(234);

以上会被替换成“234”吗?答案是不会,无论是多少,都会被替换为“a”。想要实现“234”继续往下看。

1.3 有参数宏定义中#的用法

#define STR(str) #str

以上宏定义是将参数str两端加上字符串的“”,即str内容是什么就替换成相应的字符串。但是以下情况会出错:

  • STR()),编译器不会把中间的“)”当作参数;
  • STR(,),编译器不会把“,”当作参数;
  • STR(a,b),如果参数多了,编译器会把多余的参数舍去;
  • STR((a,b)),编译器会解读"(a,b)"为参数

1.4 有参数宏定义中##的用法

#define SUB(str) L##str

以上宏定义会在形参str前加上L。

比如代码:SUB("123")就会被替换为L"123"。再比如

#define FUN(a,b) vo##a##b()
...
FUN(id ma,in);

以上会被替换为:void main()

要说明#和##区别,首先看如下代码:

 1 #include <iostream>
 2 #define t01(x) test##x
 3 #define t02(y) #y
 4 
 5 using namespace std;
 6 int main() {
 7     int test1 = 10;
 8     cout<<t01(1)<<endl;
 9     cout<<t02(test1)<<endl;
10     return 0;
11 }

输出为:

10
test1

##是链接符号,可用于参数连接,如代码行2所示;

#出现在宏定义中的#是将跟在其后的的参数转换成一个字符串,即字符串化,如代码行3所示。

 

1.5 条件编译

条件预处理器的结构与if选择结构很像。 

#ifdef NULL
    #define NULL 0
#endif

可以只在调试时进行编译,调试开关可以使用一个宏来实现,如下所示:

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;
#endif

如果在指令 #ifdef DEBUG 之前已经定义了符号常量 DEBUG,则会对程序中的 cerr 语句进行编译。您可以使用 #if 0 语句注释掉程序的一部分,如下所示:

#if 0
   不进行编译的代码
#endif

示例:

 1 #include <iostream>
 2 using namespace std;
 3 #define DEBUG
 4  
 5 #define MIN(a,b) (((a)<(b)) ? a : b)
 6  
 7 int main ()
 8 {
 9    int i, j;
10    i = 100;
11    j = 30;
12 #ifdef DEBUG
13    cerr <<"Trace: Inside main function" << endl;
14 #endif
15  
16 #if 0
17    /* 这是注释部分 */
18    cout << MKSTR(HELLO C++) << endl;
19 #endif
20  
21    cout <<"The minimum is " << MIN(i, j) << endl;
22  
23 #ifdef DEBUG
24    cerr <<"Trace: Coming out of main function" << endl;
25 #endif
26     return 0;
27 }

输出:

Trace: Inside main function
Trace: Coming out of main function
The minimum is 30

 

1.6 预定义宏

C++提供了一些预定义宏:

描述
__LINE__ 在程序编译时包含当前行号
__FILE__ 在程序编译时包含当前文件名
__DATE__ 包含一个形式为month/day/year的字符串,它代表源文件转换为目标文件的日期
__TIME__ 包含一个形式为hour:minute:second的字符串,它表示程序被编译的时间

示例:

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int main() {
 5     cout << "Value of __LINE__ : " << __LINE__ << endl;
 6     cout << "Value of __FILE__ : " << __FILE__ << endl;
 7     cout << "Value of __DATE__ : " << __DATE__ << endl;
 8     cout << "Value of __TIME__ : " << __TIME__ << endl;
 9 
10     return 0;
11 }

输出:

Value of __LINE__ : 5
Value of __FILE__ : /home/howardy/projects/CLion_Projects/Date0927/main.cpp
Value of __DATE__ : Sep 27 2020
Value of __TIME__ : 20:57:57

 

转载自:C++中的宏定义详解

 

posted @ 2020-08-12 16:36  运运翻牌了Howardy  阅读(1727)  评论(0)    收藏  举报