引例
在之前的学习中,我们了解到用宏定义来实现一些简单的功能可能会比函数来得更简便一些,因为函数在每次调用中都会申请并占用栈空间。但是在宏定义中藏有很多陷阱,相比来说,函数可能才是我们正确的选择,下面用例子来证明:
实现求1-100的平方:
用函数:
#include <stdio.h>
int Square(x)
{
return x * x;
}
int main(void)
{
int i = 1;
while (i <= 100)
{
printf("%d的平方是%d\n", i - 1, Square(i++));
}
return 0;
}
结果很正常:
接下来是用宏定义来实现:
#include <stdio.h>
#define SQUARE(x) ((x) * (x))
int main(void)
{
int i = 1;
while (i <= 100)
{
printf("%d的平方是%d\n", i - 1, SQUARE(i++));
}
return 0;
}
结果却不正常了
其实其中的
printf("%d的平方是%d\n", i - 1, SQUARE(i++));
等价于
printf("%d的平方是%d\n", i - 1, (i++) * (i++));
(入栈的顺序是从右到左,即i++先计算,再计算i-1)
在这i被加了两次,导致结果出现错误。
那我们应该如何在要反复调用函数的情况下,提高使用函数来解决问题时的效率呢?(即如何让函数的调用不用反复申请栈空间,占用栈空间)
内联函数
只需:inline + 函数()
#include <stdio.h>
inline int Square(x);
inline int Square(x)
{
return x * x;
}
int main(void)
{
int i = 1;
while (i <= 100)
{
printf("%d的平方是%d\n", i - 1, Square(i++));
}
return 0;
}
但是并能因为内联函数能提升代码运行效率,而把所有函数都写成内联函数
#和##
#include <stdio.h>
#define STR(s) # s
int main(void)
{
printf("%s", STR(LOVE));
return 0;
}
代码中LOVE本不是字符串,且printf函数中是%s,只能打印字符串类型,但是结果却是可以正常打印的。
注意:在实参的传入中,出现多个空格会变成一个空格,如果出现像"的符号,结果会自动加上\
验证:
#include <stdio.h>
#define STR(s) # s
int main(void)
{
printf(STR(Hello % s num = % d), STR(World), 520);
return 0;
}
#include <stdio.h>
#define CON(x, y) x ## y
int main(void)
{
printf("%d", CON(5, 20));
return 0;
}
可变参数
其中
#define SHOWLIST(...) printf(#__VA_ARGS__)
...和__VA_ARGS__是固定搭配
#include <stdio.h>
#define SHOWLIST(...) printf(#__VA_ARGS__)
int main(void)
{
SHOWLIST(520, LOVE, 1314);
return 0;
}
结果:
可变参数是可以接受空参数的
#include <stdio.h>
#define PRINT(format, ...) printf(# format, ##__VA_ARGS__)
int main(void)
{
PRINT(num = % d\n, 520);
PRINT(LOVE);
return 0;
}
结果:
注意:逗号(,)可以终止#符号,即把#和,之间的内容转换为字符串。