本期话题
今天聊一道c语言关于宏定义的笔试题:“写一个标准宏min ,这个宏输入两个参数并返回较小的一个。”
聊一聊
这道题考察的是 c 语言宏定义的知识。我们很容易会想到下边的答案:
#define min(a,b) ((a) < (b) ? (a) : (b)) 宏定义会在编译的时候进行替换展开。最好将宏中的参数用括号括起来。这样就避免了当一个表达式同时含有宏定义和其他高优先级运算符时,破坏整个表达式的运算顺序 。 上边的答案解决了一些问题,但是会不会存在其他漏洞呢?如果我们用这个宏进行比较least = min(i++, j++); 替换之后
least = ((i++) < (j++) ? (i++) : (j++)); 无论 i 或者 j 谁小,都会做两次自增运算。导致出现 i 和 j 完成比较后出现错误。 如何消除这种参数变化引起的副作用呢?答案是,用语句表达式来定义这个宏。
注意,语句表达式是 gnu c 对 c语言标准的扩展,允许在一个表达式里内嵌语句。 语句表达式最外面使用小括号()括起来,里面一对大括号 {} 包起来的是代码块,代码块里允许内嵌各种语句。 在语句表达式中用两个临时变量暂时存储这两个参数。
#define min_t(x, y) ({
int _x = x;
int _y = y; _x < _y ? _x : _y;
}) 在语句表达式中,定义了两个局部变量 _x、_y 来存储宏参数 x 和 y 的值,然后用 _x、_y 比较大小。这样就避免了两次自增运算引起的问题。 然而,上边的宏定义中,也存在不足,你知道是什么吗? 那就是,临时变量的数据类型为 int 型。也就是说,这个宏定义只能比较两个整型数据。 如何完善这个宏定义,使其能够支持任意类型的数据比较大小呢? 当然,我们可以这样写#define min_t(type, x, y) ({
type _x = x;
type _y = y;
_x < _y ? _x : _y;
}) 但是,这个宏就有三个参数了,每次比较数据大小,还需要将参数类型 type 传进去。 别着急,肯定有办法弥补这个不足。也就是,想办法获取比较数据的类型。 对于 gnu c 来说,没问题。因为它扩展了一个关键字 typeof,可以获取数据类型。对于其他版本的 c 语言,需要查看手册进行考证,在此不展开介绍。 最终的优化结果如下#define min(x,y) {
typeof(x) _x = (x);
typeof(y) _y = (y);
(void)(&_x = &_y);
_x < _y ? _x : _y;
}) 这个答案比较完美了。 其中 (void)(&x==&y) 是用于检查 x 和 y 的类型是否相同。它有两个作用: 一是用来给用户提示一个警告。对于不同类型的指针比较,编译器会发出一个警告,提示两种数据的类型不同。
二是两个数进行比较运算,运算的结果却没有用到,有些编译器可能会给出一个 warning,加一个(void)后,就可以消除这个警告。
好了,到这,整个宏定义面试题的各种解法就分析完毕了。看完之后,是否有所收获呢? 感谢阅读,加油~
小麦黄曲霉毒素检测仪的功能特点是什么
七牛云入选《2021 中国数字化转型服务商 TOP100 榜单》
年度硬件工程师使用率最高的十大元器件
三款新iPhone均支持USBPD快充 谁才是最大受益者
GPS车载导航仪多数辐射超标定位不准
c语言宏定义用法规则
上海电动公交一台车配两组电池
Redmi K40采用高通骁龙870处理器
小米官方正式公布了自家的可折叠手机
华为Mate9发布 华为首次“金融级别芯片安全硬件”麒麟960为设备保驾护航
美高森美推出用于SmartFusion 2 SoC FPGA的基础原型构建平台的入门者工具套件
WiSA将在CES 2023上演示由WiSA DS技术支持的无线5.1.4杜比全景声条形音箱系统平台
美国禁令将迫使中国完全实现自给自足
FPGA的程序固化步骤简析
小牛N1s电动车上手体验 售价5999元是否值得买
一种基于毒性样本敏感性的有效后门防御!
什么是实时监控系统?
华为畅享10 Plus正式发布搭载了升降式摄像头设计和4800万AI三摄
AI比人类管理区块链更有效再也不用盯“三点钟群”
机器人教育能给孩子们带来什么好处