一道编程题让老程序员邹起了眉头,这样的题你会怎么解?
对程序员来说,程序的魅力在于它的变化无穷,对于一门计算机语言来说,他的基础语法是固定有限的,可是编程的花样却是千变万化,无法穷举,可以用它做出无数个不同领域,不同业务,形形色色的产品,正因为这么灵活,关于编程的题目,也是自然很多,想必面试过的程序员都见过各种各样的面试题,有简单的,有“造火箭”的,有非常挑战大脑思考力的等等,近期,一名程序员网友就被一道编程题难住了,他把这样的题目分享给了大家。
根据这名程序员的分享,可以看出应该是c++编程题,不过重在考察程序员的思路,是考察程序员的思考能力,题目内容如下图,具体的操作要求是在pass函数中进行一番操作,然后使得第二个打印语句输出 456,这个题目看上去很一般,不过与往常我们的情况不一样的地方是pass函数并不可以传参,传引用什么的,第二个方法如何改变x值呢?针对这样的情况,让我们看看有没有程序员网友可以给出让人眼睛一亮的方案吧!
网友一:pass函数里面print 456,然后exit。 保证屏幕第二个打印的是456
上世是朵花:这么做输出的结果与想要的结果是一样的,不过请注意审题,题目中的要求是:“使得第二个打印语句输出 456”,你这算是阻止了第二个语句的打印,重新伪造了一个打印语句。
网友二:64位系统gcc 测试通过。不同编译器和系统会有所不同。int tmp; *(&tmp+8) = 456;
上世是朵花:虽然没验证这段代码,但是已经看出这名网友的思路是通过内存寻址的方式改变x的值,这是一个思路。
网友三:在C中调函数会创建一个栈帧,栈帧范围是2指针(rbp,rsp)确定,栈扩张是从地址高到低,在pass中定义变量x1,地址减去一定值访问main中的x。这个值跟编译时优化程度有关。g++ -O2优化,会省掉创建栈帧的指令和内存分配,x的地址即x1减int宽度。可以在pass中加两行:int x1;*reinterpret_cast<int*>(reinterpret_cast<uint64_ptr>(&x1)-sizeof(int)) = 456;使用g++ -O2 -std=cpp11编译
上世是朵花:这名网友说出了实现的思路,核心思想与网友二差不多,但是考虑到的更细致一点。
网友四:从上面的回答可以看出你们这些程序员c语言基础之差。
上世是朵花:评论题目就行,评论人就不友好了。
网易员工:第二个打印语句不一定是主函数里面的第二个printf吧
上世是朵花:这不就是“网友一”的思路么?
网友六:这是脑筋急转弯吧。
上世是朵花:这名网友是这么认为的,看你怎么看了。
腾讯员工:如果是单解这道题,就从pass里的临时变量地址往上遍历,发现了123的值,就姑且认为就是那个x了,然后改成456。不过这类题很古董了,现在写业务代码的同学大把都不知道。
上世是朵花:有道理,除了遍历寻址的方式好像还真想不到其他更好的办法。
网友八:用堆栈溢出来做的我一律不通过。这叫ub,ub的东西你也能告诉我这是正确的?
上世是朵花:这名网友diss了一部分网友,不过更期待的是你能给出高明的办法。
从上面网友的评论中可以看出两种思路,一种是通过“障眼法”的方式达到与预期结果一致,这个思路也是很值得赞的,不过仔细审题的话,有点不符合题目中的要求,第二种思路是通过内存寻址的方式找到x的指针位置,然后给其赋值456,这种做法是符合了题目中的要求,不过在我们实际做项目中,这样的方法我们都不会去用的,因为在实际项目中,变量之多,使用指针是很危险的一个行为了,最后很可能会出现一些很奇怪的问题,还不好找原因,这也是为什么好多高级计算机语言中废除了c++中指针这个特性的原因,顶多是会用一用引用,指针就完全废弃了,当然,这只是一道面试题,只要符合要求就行,也不需要考虑的太多,那么接下来,我抛出一个问题,面试官出这样的问题又是想考察程序员的什么呢?请说出你的看法来,下方评论区欢迎你!
以上所有图片均来之互联网
大家好,我是“上世是朵花”。如果你有什么好的看法或者观点可以在评论区展现你的才华,互动交流,如果想进一步了解我,那就关注我吧!