网站首页 > 文章精选 正文
1. 最常见的实现方法
在面试或者笔试中,经常会碰到“用宏实现求两个数中的最大数”这个题目,大家看到这个题目,觉得很容易实现,认为这有什么难度呢,随手就是一个:
#define MAX(x, y) \
((x) > (y) ? (x) : (y))
注:用括号将宏定义整个括起来,在任何时候,都是一个好习惯。
如果能写出上边这个宏,你这道题的考试就能交差了,然后觉得对自己来说就是随手一写的事儿,那可就大错特错了。因为以上写法的宏,虽然也能拿到分数,但是在面试者或者笔试阅卷者看来,你也不过如此,你也只是茫茫人海中平凡的一员。那么对于这道平淡无奇的题目来说,如何给考官一个眼前一亮,豁然开朗的印象,可以尝试下使用下边几种方法来实现。
上边那个宏定义,一般情况下,是可以满足需求的,但是对于一些参数具有副作用的情况,就很容易出现意想不到的结果了。比如:
int a = 1;
int b = 10;
int max = MAX(a++, b++);
// 宏定义展开:
((a++) > (b++) ? (a++) : (b++));
以上例子,结果会根据编译器的差异,产生一些意外的结果,这些绝对不会是程序开发者想要的结果,自己可以思考下原因......
2. 防止参数副作用的实现方法
为了防止宏定义的两个参数存在副作用的情况,可以将传递给宏定义的参数,在对比之前,保留一份备份,用备份参数来进行对比,总不会错了吧,并且这样实现,参数的副作用仅计算一次,不会影响对比的结果,实现方式如下MAX_2:
#define MAX_2(x, y) ({\
int _x = (x); \
int _y = (y); \
_x > _y ? _x : _y; \
})
然而,很快就发现,以上MAX_2宏定义,仅仅是用在对比两个int型参数时,实际情况可能对比的是unsigned char,或者其他的类型,那么这个宏定义也不能很好地达到预期的效果。
3. 指定参数类型的实现方法
继续改进,将要对比的参数类型以一个参数的形式传递给宏定义,比如下面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,最后发现是一个小符号错误的情况,太多的无奈,不再多说......
4. 相对最安全的实现方法
以上情况描述的问题,也是有方法来解决的,比如下面这个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,引起开发者注意,可以提前消灭隐患。
5. 总结
经过以上几种写法的对比,会发现最后一种MAX_4宏定义的使用还是很安全的。如果应试者能够在笔试中很快地写出MAX_4宏定义的实现方式,我相信绝对会给考官们眼前一亮,绝对是惊艳的效果,让你在众多面试者中脱颖而出。
如果以上四种方式都达不到你需要的效果,那么我就只能再想办法来解决了,因为MAX_4宏定义是目前我的认知范围内,最安全的实现“宏定义求两个数中的最大值”的方法。随时欢迎朋友们分享更好的实现方法来相互学习。
猜你喜欢
- 2025-05-10 Java手写一个bitmap(java手写代码)
- 2025-05-10 MySQL有哪些实现方式?何为插入,何为更新?
- 2025-05-10 自学 C++ 第 6 课 二维数组找最值
- 2025-05-10 斐波那契查找算法(斐波那契查找算法java)
- 2025-05-10 YARN 资源调度器 CapacityScheduler 原理
- 2025-05-10 8张图带你全面了解kafka的核心机制
- 2025-05-10 java数据类型的转换以及精度丢失(java中基本数据类型转换)
- 2025-05-10 异或的魅力!图解「数组中两个数的最大异或值」
- 2025-05-10 基础函数20例,案例解读,再不掌握就真的Out了
- 2025-05-10 C++如何定义函数重载?linux C++第6讲
- 05-14TS,TypeScript,Windows环境下构建环境,安装、编译且运行
- 05-14TypeScript 也能开发AI应用了!
- 05-14搞懂 TypeScript 装饰器
- 05-14前端小哥哥:如何使用typescript开发实战项目?
- 05-14在 React 项目中,一般怎么处理错误?
- 05-14react19 常用状态管理
- 05-14Vue3开发极简入门(2):TypeScript定义对象类型
- 05-14C#与TypeScript语法深度对比
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)