用一个宏实现求两个数中的最大数

用一个宏实现求两个数中的最大数

在面试或者笔试中,常常会碰到“用一个宏实现求两个数中的最大数”这个题目,通常状况下,你们看到这个问题,以为很容易实现,这有什么难度呢,随手就是一个:面试

#define MAX(x, y) \
        ((x) > (y) ? (x) : (y))

注:用括号将宏定义整个括起来,在任什么时候候,都是一个好习惯。
若是能写出上边这个宏,你这道题的考试就能交差了,而后以为对本身来讲就是随手一写的事儿,那可就大错特错了。由于以上写法的宏定义,虽然也能拿到分数,可是在面试者或者笔试阅卷者看来,你也不过如此,你也只是茫茫人海中平凡的一员。那么对于这道平淡无奇的题目来讲,如何给考官一个眼前一亮,豁然开朗的印象,能够尝试下使用下边几种方法来实现。安全

上边那个宏定义,通常状况下,是能够知足需求的,可是对于一些参数具备反作用的状况,就很容易出现意想不到的结果了。好比:学习

int a = 1;
int b = 10;
int max = MAX(a++, b++);
// 宏定义展开:
((a++) > (b++) ? (a++) : (b++));

以上例子,结果会根据编译器的差别,产生一些意外的结果,这些绝对不会是程序开发者想要的结果,本身能够思考下...code

为了防止宏定义的两个参数存在反作用的状况,能够将传递给宏定义的参数,在对比以前,保留一份备份,用备份参数来进行对比,总不会错了吧,而且这样实现,参数的反作用仅计算一次,不会影响对比的结果,实现方式以下MAX_2:开发

#define MAX_2(x, y) ({\
        int _x = (x); \
        int _y = (y); \
        _x > _y ? _x : _y; \
})

然而,很快就发现,以上MAX_2宏定义,仅仅是用在对比两个int型参数时,实际状况可能对比的是unsigned char,或者其余的类型,那么这个宏定义也不能很好地实现预期效果。
那么,继续改进,将要对比的参数类型以一个参数的形式传递给宏定义,好比下面MAX_3:编译器

#define MAX_3(type, x, y) ({\
        type _x = (x); \
        type _y = (y); \
        _x > _y ? _x : _y; \
})

这样,宏定义要对比的两个参数的参数类型,以参数的形式传递给宏定义,在宏定义中,type参数,将是宏定义中传递的那个参数类型,使用方法以下:编译

unsigned char c = 'A';
unsigned char d = 'B'

MAX_3(unsigned char, c, d);

MAX_3宏定义,很好地实现了对于不一样类型的两个参数求最大值的功能,可是先不要过高兴,由于MAX_3仍是存在些缺点的,好比,对于一些粗枝大叶,致使传递的两个参数,存在和第一个参数类型不一致的状况,以下:程序

int a = 100;
unsigned char c = 'H';

MAX_3(unsigned char, a, c);

以上状况,可能只是手误,可是这个意外确实存在了,而MAX_3宏定义也确实会正常执行,可是结果可能就不是实现者的本意,而在代码中也很难被查出来,你们应该都有花费大量时间查Bug,最后发现是一个小符号错误的状况,太无奈,再也不多说...
以上状况,也是有方法的,好比下面这个MAX_4宏定义:方法

#define MAX_4(x, y) ({\
        typeof(x) _x = (x); \
        typeof(y) _y = (y); \
        (void)(&_x == &_y); \
        _x > _y ? _x : _y; \
})

MAX_4宏定义,经过typeof关键字,来获取参数的类型,并保存参数的一份拷贝,防止参数反作用影响对比结果,再经过(void)(&_x == &_y);来对比两个参数类型,若是不是同一种类型,在编译阶段就会报出warning,引发开发者注意,提早消灭隐患。笔试

综上所述,若是应试者可以在笔试中很快地写出MAX_4宏定义的实现方式,我相信绝对会给考官们眼前一亮,甚至是惊艳的效果。 若是以上四种方式都达不到你须要的效果,那么我也没办法了,由于MAX_4宏定义能够说是个人认知范围内,最安全的实现“宏定义求两个数中的最大值”的方法了。随时欢迎朋友们有更好的实现方法来学习。

相关文章
相关标签/搜索