Skip to main content
 首页 » 编程设计

C++带参数宏解惑教程

2022年07月19日131TianFang

本文介绍使用带参数宏过程中遇到的几个问题和坑,希望对你有帮助。

带参数宏定义语法如下:

#define macro_identifier(<arg_list>) <token_sequence> 

不能有空格分隔macro_identifier 和 “(” 。可选参数arg_list是一组用逗号分割的标识符,与函数参数类似。但在括号参数内部的逗号被视为参数的一部分,不是参数分隔符,每个逗号分割的标识符扮演形参或占位符角色。

调用宏语法:

macro_identifier<whitespace>(<actual_arg_list>) 

看上去和函数调用一样,但有一些差异、副作用以及潜在坑。可选的_actual_arg_list_必须包含与#define行定义形式参数_arg_list_数量相同的逗号分隔的标记序列(也称为实际参数),如果两个参数数量不一致会导致错误。

宏调调用即两组参数替换过程。首先,_macro_identifier_和圆括号内的参数被_token_sequence_替换。接下来,任何出现在_token_sequence_中的形式参数都被出现在_actual_arg_list_中的相应的实际参数所替换,与简单宏定义一样,需要重新扫描以检测任何符合扩展条件的嵌入宏标识符。

嵌套括号和逗号

actual_arg_list 可以包含嵌套圆括号(但必须要对称),逗号出现在原括号内部的不作为参数分隔符。

#define ERRMSG(x, str) printf("Error: %d \n%s", x, str) 
#define SUM(x,y)  ((x) + (y)) 
 
ERRMSG(2, "Press Enter, then ESC"); 
/*展开结果为:  printf("Error: %d \n%s", 2, "Press Enter, then ESC"); */ 
 
return SUM(f(i, j), g(k, l)); 
/*展开结果为:  return ( (f(i, j)) + (g(k, l)) ); */ 

一些坑

函数调用与宏调用有一些差异。宏调用没有内置类型检查,所以形式参数与实际参数类型不匹配会产生奇怪、难以调试结果,且没有任何警告。宏调用还可能导致难以理解的问题,特别是当实际参数被解析多次时。请看示例:

 
#define CUBE(x)  ( (x) * (x) * (x) ) 
 
int cube(int x) { 
   return x*x*x; 
} 
 
 
int b = 0, a = 3; 
b = cube(a++); 
/* 给cube()传的实参 a = 3; 所以 b = 27; 现在 a = 4 */ 
 
 
a = 3; 
b = CUBE(a++); 
/* 扩展为 ( (a++) * (a++) * (a++) ); 再次 b = 27 ,但现在 a = 6 */ 

使用#转换实参至字符串

在形式参数前面可以使用#号,用于转换实际参数,使得替换之后为字符串:

#define TRACE(flag) printf(#flag "=%d\n", flag) 
 
 
/* 调用宏*/ 
int highval = 1024; 
TRACE(highval); 
 
/* 
 
 
/*结果为下面代码*/ 
int highval = 1024; 
printf("highval" "=%d\n", highval); 
 
/*进一步转为下面代码*/ 
int highval = 1024; 
printf("highval=%d\n", highval); 

再看一个示例:

// stringizer.cpp 
#include <stdio.h> 
#define stringer( x ) printf_s( #x "\n" ) 
 
int main() { 
   stringer( In quotes in the printf function call ); 
   stringer( "In quotes when printed to the screen" ); 
   stringer( "This: \"  prints an escaped double quote" ); 
} 

main函数代码被扩展为:

int main() { 
   printf_s( "In quotes in the printf function call" "\n" ); 
   printf_s( "\"In quotes when printed to the screen\"" "\n" ); 
   printf_s( "\"This: \\\" prints an escaped double quote\"" "\n" ); 
} 

最后输出结果为:

In quotes in the printf function call 
"In quotes when printed to the screen" 
"This: \"  prints an escaped double quote" 

本文参考链接:https://blog.csdn.net/neweastsun/article/details/124093584