看到这么一道面试题
#include <stdio.h> void main() { int a=1,b=0,c=-1,d=0; d=++a||++b&&++c; printf("d=%d", d); //output 1; return; }
我不理解为什么 d 会变成 1 而不是 2 。我知道所谓“短路”,但是无论如何,最左边 d=++a 这个表达式都会被 evaluate 啊。
#include <stdio.h> void main() { int a=1,b=0,c=-1,d=0; d=++a; printf("d=%d", d); //output 2 return; }
这个结果就得 2 。
为什么呢?
![]() | 1 stackpop 2016-03-11 23:22:27 +08:00 运算符优先级 |
2 c0nnax 2016-03-11 23:22:31 +08:00 前面那个是逻辑吧 |
![]() | 3 raysonx 2016-03-11 23:23:04 +08:00 via Android ||是算符,返回果只可能是 1 或 0 。 |
![]() | 4 ll0xff 2016-03-11 23:23:44 +08:00 因为 (++a||++b&&++c )实际是个 boolean 值。 |
![]() | 5 KyL OP 好吧,我明白了。 `d=++a||++b&&++c;`的执行顺序应该是 `d=((++a)||((++b)&&(++c)))` ++a = 2 直接就决定了 d="true",也就是 d=1 |
6 ben3ai 2016-03-11 23:27:24 +08:00 via iPhone 这个表达式中=运算符的优先级是最低的,=右边, and 优先级高于 or ,++a 为 true ,编译器应该是把逻辑真作 1 处理了 |
![]() | 7 ETiV 2016-03-11 23:30:04 +08:00 ![]() 因为 "||", "&&" 被理解成了判断 true / false 并且, 从左到右, 先遇到了 ||, 所以只要 || 左边的结果 !=0 , 就直接返回了 true. 后面的 ++b, ++c 都没有被运算到...你自己试试看吧.. |
![]() | 8 airqj 2016-03-11 23:32:07 +08:00 实际上只会算(++a) |
![]() | 9 wenyu1001 2016-03-11 23:36:36 +08:00 出现这样的代码, code review 时定会被骂,幸好只是面试题。 |
![]() | 10 r00t 2016-03-11 23:42:10 +08:00 我发现某些公司总是喜欢出这种面试题~优先级看好就 ok |
![]() | 11 oplang 2016-03-11 23:47:10 +08:00 8 楼说的对,算完(++a)就直接把值赋给等号左边了,没后面什么事 |
![]() | 12 neilp 2016-03-11 23:55:52 +08:00 via iPhone 不要跟 js 搞混了 |
![]() | 13 theohateonion 2016-03-12 02:02:45 +08:00 ![]() 。。个人强烈反对去研究这种代码,感觉一点意义都没有。。这种代码的出现本身就是一个错误,无数的小白因为这些东西把编程看作洪水猛兽,其实真正的编程真的很美不是吗。 |
![]() | 14 Ge4Los 2016-03-12 02:24:21 +08:00 1. 逻辑运算符的 || 优先级高于赋值运符 =。 2. || 运算符的短路特性。|| 前面条件为真, 后面的条件是不需要继续运算。 3. C 中布尔值真为 1 。 这题涉及的内容属于 C 专有的特性。 |
![]() | 15 shiji 2016-03-12 02:38:32 +08:00 @theohateonion 同强烈反对,这就像小学的奥数题,费时,麻烦,并且将来没什么卵用。 也许只会在面试这种环节出现吧,一辈子再也遇不到了。 |
![]() | 17 arslion 2016-03-12 02:55:40 +08:00 |
![]() | 19 yangqi 2016-03-12 05:00:03 +08:00 运算符优先级,最基本的东西,能看出一个人的基本功 |
![]() | 20 shiji 2016-03-12 05:08:02 +08:00 @Valyrian 是挺好玩的,但是拿来一道题几乎没人能会做,反正我学的奥数几乎都是针对每一种题型,记忆住解题的规律,然后这一类题就都会了。等哪一天忘了那个规律或者是公式,脑子里就啥也不剩了。 |
21 chaoerzheng 2016-03-12 08:33:59 +08:00 我没算结果,写“ d=++a||++b&&++c;”的这个人是垃圾。 |
22 ershisi 2016-03-12 08:49:35 +08:00 这个题个人认为是逻辑运算的编译阶段优先级。右侧优先于左侧。另外,这种题做完理解意思就行了。生产环境中你要是这么写代码肯定自己都想骂自己。 |
![]() | 24 kiwi95 2016-03-12 09:13:48 +08:00 via Android 面试如果问这种题,直接拒绝回答就是了 |
![]() | 25 kiwi95 2016-03-12 09:19:57 +08:00 via Android 哦,好像看错了, |
27 jiangtao92 2016-03-12 10:15:38 +08:00 这个算是逻辑运算吧,不是 true 就是 false ! |
![]() | 28 matthewz 2016-03-12 10:16:10 +08:00 via iPhone 这道题还可以啊 不算是那种++++++a 的傻逼题 |
![]() | 29 wezzard 2016-03-12 11:46:11 +08:00 我回答:「不起我不言程。」 |
![]() | 30 wezzard 2016-03-12 11:58:02 +08:00 看了看,道考的是算以及言面布到底是甚。 但是在代 C 言器面,段言的代是法通的,因: 1 )我不知道言的,但是 C 言的 main 函是需要返回 int 型的值的; 2 )我不知道言的,但是 xxx || xxx && xxx 法在代 C 言器的默警告定下是警的; |
32 qian19876025 2016-03-12 12:23:07 +08:00 劝楼主多看看书 其他的都白说 你到现在如何断句都有问题 |
![]() | 33 Testalias 2016-03-12 12:51:42 +08:00 看到 void main 就知道出处了, 出这个面试题的应该不怎么写 C 。 |
34 jukka 2016-03-12 12:55:24 +08:00 别在这些东西上浪费生命。 |
![]() | 36 Qiangyuan 2016-03-12 15:15:47 +08:00 这题不错,考察程序基本功 |
![]() | 37 donghouhe 2016-03-12 15:19:53 +08:00via iPad 学习这种是能加深理解的,还是有点用的。如果你是做不出才愤怒地说没用,那就错了。如果你能轻松做出,那才有资格说。 |
![]() | 38 sagnitude 2016-03-12 15:55:27 +08:00 虽然很多类似的题目毫无意义,但是这道题确实考察了基础 有些题目纠结于++符号,是毫无意义的,碰到那种代码,我会在代码规范里加上“类似情况必须加括号” 这道题说的是赋值符号,和语言基本无关,楼上几位结论下太快的可以再看几眼题目 |
![]() | 39 JJFJJ 2016-03-12 16:02:27 +08:00 写这样的代码,在 CodeReview 和以后维护的时候,会被人骂死的。 为什么不加括号来解决优先级的问题呢 |
![]() | 40 syhilyhw 2016-03-12 16:10:54 +08:00 这个你只能怪+++++ |
![]() | 42 wuhanchu 2016-03-12 16:58:54 +08:00 差点被你被你骗了 先算++a||++b&&++c 再赋值。。哎呀 这个问题 真是折磨人 |
![]() | 43 vagarlee 2016-03-12 17:19:42 +08:00 d=(++a||++b&&++c) ++a||++b&&++c 的值返回的是 1 因为|| |
44 aksoft 2016-03-12 17:22:04 +08:00 码农和程序员的区别。 |
45 kingoldlucky 2016-03-12 17:59:01 +08:00 这道题真的很简单..真的很简单.. 一眼扫过去就知道结果不是 0 就是 1 |
46 kingoldlucky 2016-03-12 18:00:16 +08:00 而且看完第一个++a|| 到这里了就知道结果一定为 1 只要有一个为真,表达式就为真 |
47 kingoldlucky 2016-03-12 18:02:27 +08:00 楼上那么多反对这道题的,C 语言真的是弱爆了,校招怎么找到工作啊. |
![]() | 50 ikw 2016-03-12 18:58:16 +08:00 |
![]() | 51 ikw 2016-03-12 19:12:58 +08:00 @kingoldlucky 请教一下,我从维基百科看到的运算符优先级中 && 是比 || 高一级的,那在一个语句里同时出现,为什么不处理 &&? 我知道 || 的短路效果,但是按优先级来看,难道不是应该先处理 && 吗? 从短路效果这点来看,无论什么运算,只要 || 前面为真,放在 || 之后都不运算,那 || 优先级的意义在哪?尤其是还专门分别给 && 和 || 定义 13 , 14 两个优先级。 https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B |
![]() | 52 Viztor &nbs; 2016-03-12 19:24:11 +08:00 ![]() |
53 kingoldlucky 2016-03-12 19:36:49 +08:00 @zwpaper 这道题 || 右边的所有结果对最后的 0 1 不构成影响 |
55 nicevar 2016-03-12 21:05:22 +08:00 这种问题看汇编代码最清晰,哪能记得住那么多优先级 |
56 bp0 2016-03-13 00:03:10 +08:00 ![]() @KyL 这道题考的是前置++的运算时间,以及||和&&优先级的关系。 @zwpaper 不是不计算,而是还没开始计算就被跳过去了。如果优先级反过来,结果就是 0 了。 正因为&&的优先级高,所以表达式就像 @Viztor 说的是 ++A || (++B && ++C) ,算完++A 后,因为结果是 2 ,所以跳到给 d 赋值了(汇编级别而言)。 如果是||的优先级高,那么表达式就是 (++A || ++B) &&++C 。当++A 算完以后,不用算++B 。但是还要算++C 的,而 C 的初值是-1 。++C 的意思是先++,然后再&&。而-1 自增后是 0 。 所以,如果||的优先级高,那么 d 的值应该是 0 。 |
![]() | 57 cuteshell 2016-03-13 12:23:22 +08:00 @zwpaper 是我弄错了,如果是同优先级++a||++b&&++c 的结果就是 false 了,应该是++a||(++b&&++c)就对了。 |
![]() | 58 KyL OP @theohateonion 谁说不是呢。这种代码老老实实用括号括起来就什么问题都没有。可是谁让很多公司就爱出这中面试题呢? |
![]() | @KyL 我觉得公司这么考考虑的应该是看你对一门语言掌握的深度如何,其实这样还是有道理的,但是现在的情况是,作为一名大四狗,我在四年的学习中看到很多老师和教材也把这些题作为了教学的重点,导致很多学生失去了编程的兴趣,令人扼腕 |
![]() | 60 theohateonion 2016-03-13 14:48:39 +08:00 @KyL 也可能是我们学校教学方面还存在着问题吧(西安某 985 ) |
61 yuchting 2016-03-13 14:50:29 +08:00 4 年多没碰 C 了,不过看了一下,感觉等号右边是个 bool 式,那么赋值不是 1 就是 0 ,到不了其他情况去的吧?这个是编译器干的,再高级一点的语言,编译器直接报错的。 出这个题的目的应该是判断“++”在左边或右边的情况,以及条件运算符从左到右的依次判断及运算舍弃的期基础知识。不要吐槽了。实际编程不会写成这样的,但是实际情况中的 bug 都是因为这个关系没有理清楚而导致的所谓的低级错误。 有些戏低级错误找起来巨麻烦, 3 年重压下找到后只想自杀,后悔当年没学好。 |