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

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

在面试或者笔试中,经常会碰到“用一个宏实现求两个数中的最大数”这个题目,一般情况下,大家看到这个问题,觉得很容易实现,这有什么难度呢,随手就是一个:

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

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

上边那个宏定义,一般情况下,是可以满足需求的,但是对于一些参数具有副作用的情况,就很容易出现意想不到的结果了。比如:

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

以上例子,结果会根据编译器的差异,产生一些意外的结果,这些绝对不会是程序开发者想要的结果,自己可以思考下...

为了防止宏定义的两个参数存在副作用的情况,可以将传递给宏定义的参数,在对比之前,保留一份备份,用备份参数来进行对比,总不会错了吧,并且这样实现,参数的副作用仅计算一次,不会影响对比的结果,实现方式如下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宏定义可以说是我的认知范围内,最安全的实现“宏定义求两个数中的最大值”的方法了。随时欢迎朋友们有更好的实现方法来学习。

原文地址:https://www.cnblogs.com/microxiami/p/11073981.html

时间: 2024-12-28 14:45:02

用一个宏实现求两个数中的最大数的相关文章

编程题:返回指针值的函数,求两个数中较大的数。

#include<stdio.h> int *max(int *x,int *y) { int *q; if(*x>*y)  q=x; else  q=y; return q; } void main() { int a,b,*p; scanf("%d,%d",&a,&b); p=max(&a,&b); printf("%d,%d,max is %d\n",a,b,*p); } 编程题:返回指针值的函数,求两个数中较

编程题:用函数调用实现,求两个数中的最小数。

#include<stdio.h> void main() { float min(float x,float y);  /*函数定义在调用的函数之后,要先声明*/ float a=3,b=4.1; printf("%.1f\n",min(a,b)); printf("%.1f\n",min(5,a*b)); printf("%.1f\n",min(b-1,min(a,b))); } float min(float x,float y

编程题:指向函数的指针,求两个数中较大的数。

#include<stdio.h> int max(x,y) { int z; if(x>y)  z=x; else  z=y; return z; } void main() { int a,b,c; int (*p)(); p=max; scanf("%d,%d",&a,&b); c=(*p)(a,b); printf("%d,%d,max is %d\n",a,b,c); } 编程题:指向函数的指针,求两个数中较大的数.,布布

【c语言】求两个数中不同的位的个数

// 求两个数中不同的位的个数 #include <stdio.h> int dcount(int a,int b) { int count = 0; int num = a ^ b; while (num) { count++; num = num & (num - 1); } return count; } int main() { printf("%d\n", dcount(3, 5)); return 0; } 版权声明:本文为博主原创文章,未经博主允许不得

请定义一个宏,比较两个数的a、b的大小,不能使用大于、小于、if语句(转载)

笔试的时候经常问这些: 方法一: #define max(a,b) ((((long)((a)-(b)))&0x80000000)?(b):(a)) 若a>b,则a-b的二进制最高位为0,与上任何数还是0,所以大数为a: 否则,a-b为负数,最高位为1,与上0x80000000(最高位为1其他为0)之后为1,所以此时最大数为b. 方法二: #define max(a,b) ((((a)-(b))&(1<<31))?(b):(a)) 方法三:      1.#define 

C#编写代码:求三个数中的最大数

static void Main(string[] args)        {            float x, y, z, temp;            Console.Write("请输入一个实数:");            x = float.Parse(Console .ReadLine() );            Console.Write("请输入一个实数:");            y = float.Parse(Console .

C语言求两个数中最大公约数

在C语言中如何求两个数的最大公约数呢?下面用三种方法进行求解. 方法一:穷举法. 先比较两个数的大小,然后找出较小数t,最后判断t为何值时两个数都能整除,此方法效率较低. 代码如下: #include<stdio.h> int main() {      int num1,num2,temp,i;      scanf("%d%d",&num1,&num2);      if(num1>num2)      {            temp=num1

写一个方法,求两个数的最大公约数和最小公倍数。

package homework0702; /* * 最大公约数 利用辗转相除法求解两个正整数的最大公约数 在循环中,只要除数不等于0,用较大的数除以较小的数,将小的一个数作为下一轮循环的大数,取得的余数作为下一轮循环较小的数,如此循环直到较小的数值为0,返回较大的数.即为最大公约数. 辗转相除法(欧几里得算法) 定理:两个整数的最大公约数等于其中较小的那个数和两数的相除余数的最大公约数.最大公约数(greatest common divisor)缩写为gcd. 最小公倍数 最小公倍数 = (a

不用”if“,”?:“,”switch“或其他判断语句,求两个数中较大的数或较小的数

以下五种方法分别求出较大的数和较小的数的方法.较小数的代码在注释中,但未运行测试. int Find1(int a, int b) { return ((a + b) + abs(a - b)) / 2; //return ((a + b) - abs(a - b)) / 2; } /* 当a大于b时,a-b为正,右移sizeof(int) * 8 - 1后,最右侧一位为0,0^1 = 0: 当a小于b时,a-b为负,右移后最右侧一位为1,1^1 = 1 */ int Find21(int a,