认识带参数宏
定义
性质
优缺点
带参数宏实例
例1 模拟函数:求两个数中的最大者
#include <stdio.h>
#define MAX(x,y) ((x)>(y)?(x):(y))
int main(void)
{
int i, j;
i = 100;
j = 98;
printf("Macro MAX(%d, %d) called: %d\n", i, j, MAX(i, j));
return 0;
}
输出:
Macro MAX(100, 98) called: 100
例2 模拟函数:判断一个数是不是偶数
#include <stdio.h>
#define IS_EVEN(n) ((n)%2 == 0)
int main(void)
{
int i;
i = 100;
printf("Macro IS_EVEN(%d) called: %d\n", i, IS_EVEN(i));
i = 97;
printf("Macro IS_EVEN(%d) called: %d\n", i, IS_EVEN(i));
return 0;
}
输出:
Macro IS_EVEN(100) called: 1
Macro IS_EVEN(97) called: 0
例3 带参数宏模拟函数:将小写字母转成大写字母
#include <stdio.h>
#define TOUPPER(c) ('a'<=(c) && (c)<='z'? (c)-'a'+'A': c)
int main(void)
{
char a1 = 'b';
printf("Macro TOUPPER(%c) called: %c\n", a1, TOUPPER(a1));
char a2 = 'B';
printf("Macro TOUPPER(%c) called: %c\n", a2, TOUPPER(a2));
return 0;
}
输出:
Macro TOUPPER(b) called: B
Macro TOUPPER(B) called: B
例4 带参数宏模拟函数:简单显示整数
#include <stdio.h>
#define PRINT_INT(n) printf("%d\n", n);
int main(void)
{
int i,j;
i = 11;
j = 2;
PRINT_INT(i/j);
return 0;
}
例5 带参数宏模拟函数:输出带有标签的整数
#include <stdio.h>
#define PRINT_INT(n) printf(#n" = %d\n", n);
int main(void)
{
int i,j;
i = 11;
j = 2;
PRINT_INT(i/j);
return 0;
}
解释:
-
#
运算符:将宏的一个参数转换为字符串常量。
例6 泛型MAX宏定义
源文件generic_max.c
#include <stdio.h>
#define GENERIC_MAX(type) \
type type##_max(type x, type y) \
{ \
return x > y? x : y; \
}
float float_max(float x, float y);
int int_max(int x, int y);
int main(void)
{
float x, y;
x = 97.0f;
y = 100.0f;
printf("function float_max(%f, %f) called: %f\n", x, y, float_max(x, y));
int i, j;
i = 100;
j = 98;
printf("function int_max(%d, %d) called: %d\n", i, j, int_max(i, j));
return 0;
}
GENERIC_MAX(float)
GENERIC_MAX(int)
截取预处理后文件generic_max.i
的片段:
float float_max(float x, float y);
int int_max(int x, int y);
int main(void)
{
float x, y;
x = 97.0f;
y = 100.0f;
printf("function float_max(%f, %f) called: %f\n", x, y, float_max(x, y));
int i, j;
i = 100;
j = 98;
printf("function int_max(%d, %d) called: %d\n", i, j, int_max(i, j));
return 0;
}
float float_max(float x, float y) { return x > y? x : y; }
int int_max(int x, int y) { return x > y? x : y; }
输出:
function float_max(97.000000, 100.000000) called: 100.000000
function int_max(100, 98) called: 100
解释:
-
##
运算符:将两个tokens(比如标识符)粘在一起形成一个token。
例7 追踪函数的调用
#include <stdio.h>
#define FUNCTION_CALLED() printf("%s called\n", __func__);
#define FUNCTION_RETURNS() printf("%s returns\n", __func__);
void f(void);
int main(void)
{
f();
return 0;
}
void f(void)
{
FUNCTION_CALLED();
printf("hello world f()\n");
FUNCTION_RETURNS();
}
输出:
f called
hello world f()
f returns
解释:
- 标识符
__func__
:存储的是当前正在执行的函数的名字的字符串。
例8 可变参数宏
#include <stdio.h>
#define TEST(condition,...) ((condition)? \
printf("Passed test: %s\n", #condition): \
printf(__VA_ARGS__))
int main(void)
{
int voltage, max_voltage;
max_voltage = 120;
voltage = 125;
TEST(voltage <= max_voltage,
"Voltage %d exceed %d\n", voltage, max_voltage);
voltage = 98;
TEST(voltage <= max_voltage,
"Voltage %d exceed %d\n", voltage, max_voltage);
return 0;
}
输出
Voltage 125 exceed 120
Passed test: voltage <= max_voltage
解释:
-
__VA_ARGS__
:表示与省略号对应的参数,且只能出现在具有可变参数的宏的替换列表中;
例9 区分同一程序的不同版本
在程序开始放置如下语句:
printf("compiled on %s at %s\n", __DATE__, __TIME__);
#include <stdio.h>
int main(void)
{
printf("compiled on %s at %s\n", __DATE__, __TIME__);
return 0;
}
输出:
compiled on Apr 6 2020 at 09:24:12
解释:
-
__DATE__
:编译的日期,格式为"mm dd yyyy"; -
__TIME__
:编译的时间,格式为"hh:mm:ss";
例10 查找出错的代码行数和文件
macrotest4.c
#include <stdio.h>
#define CHECK_ZERO(divisor) \
if (divisor == 0) \
printf("*** Attempt to divide by zero on line %d "\
"of file %s *** \n", __LINE__, __FILE__);
int main(void)
{
int i,j;
i = 100;
j = 0;
CHECK_ZERO(j);
return 0;
}
输出:
*** Attempt to divide by zero on line 15 of file macrotest4.c ***
解释:
-
__FILE__
:被编译的文件名 -
__LINE__
:被编译的文件中的行号