一道C面试题的思考

简介: C语言真的是学无止境的感觉,大部分同学大学都会开设C语言课程。很多人把C语言二级过了就感觉入门了;对于那些在做嵌入式开发的工程师,几乎每天都要接触C语言,很多人会感觉自己C语言学得很溜了。那好,咱们用一道C语言面试题来测试一下。

一、前言

C语言真的是学无止境的感觉,大部分同学大学都会开设C语言课程。很多人把C语言二级过了就感觉入门了;对于那些在做嵌入式开发的工程师,几乎每天都要接触C语言,很多人会感觉自己C语言学得很溜了。那好,咱们用一道C语言面试题来测试一下。

二、面试题

首先给出题目:
定义一个宏,求两个数中的最大数

OK,很多人应该能很快写出

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

接下来我们写一个测试程序

#define MAX(x,y) x > y ? x : y
int main(void)
{
    printf("max=%d",MAX(1,3)); //测试通过
    printf("max=%d",MAX(4,1));//测试通过
    printf("max=%d",MAX(2,2));//测试通过
    printf("max=%d",MAX(3!=3,1!=2)); //好像不是我们要的结果
    return 0;
}

我们会发现第四个测试不是我们的要结果了。这是因为宏展开后,就变成了这个样子:

printf("max=%d",3!=3>1!=2?3!=3:1!=2);

这个时候大于号(>)的优先级更高,所以就出现了问题了。

优化上面的代码

可能很多人已经想到了解决方法了,比较有经验的工程师基本也比较少犯上面的错误。
加上括号就可以解决上面的问题了。

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

OK,接下来我们再写一个测试程序

#define MAX(x,y) (x) > (y) ? (x) : (y)
int main(void)
{
    printf("sum =%d", 7 + MAX(3,4));
    return 0;
}

运行结果:
在这里插入图片描述
并不是我们所期望的11。我们将其展开后为:

7 + (3) > (4) ? (3) : (4);

这个时候加号(+)的优先级又比大于号(>)高,所以就出现了这种结果。

那我们就继续加个括号

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

到这里算是比较完整的了,在面试中要是能写出这个,那算基本功还是比较扎实的了。

那我们再写一个测试程序

#define MAX(x,y) ((x) > (y) ? (x) : (y))
int main(void)
{
    int i = 3;
    int j = 4;
    printf("max=%d",MAX(i++,j++));
    return 0;
}

运行结果:
在这里插入图片描述
这里面的j会做两次自增运算, 所以打印出来的结果是做了一次自增后的结果。

继续优化

#define MAX(type,x,y)({     \
    type _x = x;        \
    type _y = y;        \
    _x > _y ? _x : _y; \
})
int main(void)
{
    int i = 4;
    int j = 5;
    printf("max=%d\n",MAX(int,i++,j++));
    printf("max=%f\n",MAX(float,3.2,3.4));
    return 0;
}

到这里基本算比较完美了!是不是很折腾, 程序的bug就是这样一步一步修复的过程。

三、总结

如果你能一下就写出最后的代码,那说明你确实是666了,通过上面的一步一步分析是为了告诉大家,C语言真的有很多东西可以让我们去琢磨!我们也还有很长的路要走。

相关文章
|
消息中间件 设计模式 关系型数据库
面试题30天打卡-day08
面试题30天打卡-day08
29 0
|
消息中间件 存储 NoSQL
面试题30天打卡-day23
面试题30天打卡-day23
34 0
|
存储 XML Java
面试题30天打卡-day13
面试题30天打卡-day13
45 0
|
6月前
|
存储 算法 编译器
C++面试题其一
C++文件编译与执行的四个阶段 预处理:处理#include、#define等预处理指令。 编译:将源码翻译为目标代码。 汇编:将目标代码转换为机器指令。 链接:将目标文件和库文件合并生成可执行文件。 STL中的vector的实现,是怎么扩容的? vector通过动态数组实现,当容量不足时,分配更大的内存(通常是原来的两倍),复制旧数据到新内存,并释放旧内存。
86 2
|
4月前
|
JavaScript 前端开发 API
面试题总结
面试题总结
107 58
|
7月前
|
Kubernetes 调度 Docker
k8s面试题大全
本篇模拟面试官提问的各种docker,k8s问题,意在提高面试通过率,欢迎在评论区探讨,同步进步。
206 2
|
7月前
面试题 03.04:化栈为队
面试题 03.04:化栈为队
37 5
|
7月前
|
网络协议 NoSQL 数据库
C++面试题
C++面试题
|
存储 安全 Java
Java多线程并发面试题 2
Java多线程并发面试题
61 0
|
存储 算法 安全
【C++】面试题
【C++】面试题
144 0