本文介绍使用带参数宏过程中遇到的几个问题和坑,希望对你有帮助。
带参数宏定义语法如下:
#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