在知乎的https://www.zhihu.com/question/22465774/answer/660997629问题中看到了“宅学部落”发表的回答,对于其中的【定义一个宏,求两个数中的最大数】问题感触颇深。今年寒假去华为面试实习的时候就被问到了这个问题,当时基础知识掌握的并不牢靠,非常惭愧地连最简单的都没写对= =。今日看到此文,才发现其中含义颇深。
回答中的前几种如:
#define MAX(x,y) x > y ? x : y
#define MAX(x,y) (x) > (y) ? (x) : (y)
#define MAX(x,y) ((x) > (y) ? (x) : (y))
这三种其实都是对C或C++有一定理解后都能很快理解其中奥妙的存在,而第三种我认为其实已经是面试时较好的答案了。但是实际上,答主对于后缀自增符时的探讨让我发现考虑到参数类型时才能更符合实际情况使用(具体如下)
#define MAX(type,x,y)({ \
type _x = x; \
type _y = y; \
_x > _y ? _x : _y; \
})
int main(void)
{
int i = 2;
int j = 6;
printf("max=%d\n",MAX(int,i++,j++));
printf("max=%f\n",MAX(float,3.14,3.15));
return 0;
}
增加了类型符后,所传入的实参会被局部变量存储,从而计算时使用的是还未自增时的实参,这样的答案才是我们希望实现类似如下形式代码时的本意
cout << c++ << endl;
但是很明显,type这样的用法在C++中其实并不适用,为了保证数据类型的自定义,C++定义了模板类来实现这样的情况,而为了实现模板类,将会违背了题目的本意“定义一个宏”,但是对于C++来说,可能只有这样才能达到我认为的最优解吧。
为此,我将C++中能实现的宏定义最优解与模板类实现的最优解均进行了测试,发现确实使用模板类可以避免后缀自增符时的参数自增问题,具体如下:
#include <iostream>
using namespace std;
#define MAX1(x,y) ((x)>(y) ? (x) : (y))
template<typename T> T inline MAX2(T x, T y) { T _x = x; T _y = y; return (_x) > (_y) ? (_x) : (_y); }
int main()
{
int a = 3;
int b = 6;
//auto r = MAX1 (a++, b++);
auto r = MAX2(a++, b++);
cout << r << endl;
int c = 5;
cout << c++ << endl;
return 0;
}
测试得到,使用宏定义的MAX1打印r时得到的值为7,使用模板类打印r时得到的值为6,同时可以适用于多种数据类型,可见从C++实现的角度来看,可能函数的实现更为实用且易懂吧。虽说C里面有很多东西都具有较大的问题,但是宏定义在我们的代码编写生活中还是相当好用的,不过当深入地探究更为细致的问题时,可能还是使用C++解决C++自己的问题才是最好的吧。
参考文献
[1] https://www.zhihu.com/question/22465774/answer/660997629