`y=++y`, is this standard compliant? [which appears in a test by Microsoft]
我知道这看起来很熟悉,但在微软招聘实习生的测试中,这对我来说是个问题。在我看来,y=++y不符合标准,但我认为最好确定一下(不确定我比那些在MS上编写这些测试的人更好)。所以我在征求你的意见。您认为这样的表达式符合标准,不会导致未定义的行为吗?
1 2 3 4 5 6 7 8 9 10
| #include <stdio.h>
int main(){
int a = 10;
int b = 10;
a = ++a; //What ???
b = b++; //What ???
printf("%d %d
",a,b);
return 0;
} |
当使用-Wsequence-point编译时,gcc会抱怨它。(没有明确说明它是C或C++特定的问题。)
但只有四个答案:
1 2 3 4
| a) 10 10
b) 11 10
c) 10 11
d) 11 11 |
虽然一个答案并不局限于只选择一个答案(所以也许我应该选择全部四个答案?)
在我看来,在自我递增和分配之间没有序列点。所以这违反了规范。不是吗?
- 你想用C++ 03或C++ 11来回答吗?他们用不同的方式解释这些事情。
- 你是对的。这是未定义的行为。
- 是的,是ub,但我还是会选择b)作为答案:p
- @sftrabbit好吧,它甚至没有说明是C还是C++,但是请解释一下。
- imho d)是这四种情况中唯一可能发生的情况,即使是在未定义的行为中。
- 这就是Windows8卖得不好的原因吗?
- @卢奇昂:a = ++a不是ub,只有b = b++是ub。
- 对,只有c)或d)可能是正确的答案,因为b是11开头,不可能变成10[除非我们被期望不明确的行为去做"非常意想不到的事情"。
- 技巧问题:正确答案在评论中,靠近表达
- C不是C++没有用两个标记来标记这个问题。
- 让我困惑的是,我不认为任何给定的选择是正确的(如果我们不谈论UB的话)。有人能解释为什么不给e) 11 12一个可能的选择吗?
- 正如我所说,CabPulsPube不清楚它是C还是C++。
- 本规范附带的测试/面试问题的确切措辞是什么?
- @火鹰没关系。C标准对C++行为没有权威性,反之亦然。如果你想知道两者的答案,就提出两个问题。否则,这将是一堆互不相关的答案,对任何人都没有用处。
- 应该有第五个答案:不要这样写代码。
它们都是按照C++ 11定义的行为。C++ 11甚至没有序列点,所以序列点相关警告显然是过时的。赋值运算符对其参数强制排序。
编辑:
虽然每个人都同意i = ++i现在是定义明确的行为,但决定i = i++的定义是相当重要的。直观地说,我应该把它描述得很清楚,但是标准明确指出
是乌兰巴托,我看不到埃多克斯一号〔2〕在这里有什么不同。
简而言之,如果你想回答这个问题,你需要成为一个专家,在决定性的不平凡的C++ 11排序规则,看起来我不是,但似乎答案是"以上没有因为UB"。
- @ DeadMG,你能回答一个附加的问题,因为你回答了原来的问题:结果不应该是C++ 11中的EDOCX1?1吗?
- 不,为什么?还有,再问一个问题。
- @因为b = 11;和b = b++;使b仍然等于11,我们在printf中有使b等于12的后增量…对不起,我不认为这是一个单独的问题,我不明白为什么在原始列表中没有这样的选择…也许,我误解了一些事情,只是想澄清一下。
- 实际上,我现在改变主意了!b = b++是未定义的行为。发布一个答案来描述原因。
- 那么,正确的答案是什么?我以为这是乌布
- @sftrabbit:决定它是否是ub肯定是非常重要的。
- @该死的,好吧,我以书面形式提出论点!箭头表示"之前排序"。V.C."表示数值计算。这是未定义行为的原因是图中的两个星型节点没有排序。造成这种情况的主要原因来自标准的"修复后增量"部分:"++表达式的值计算是在修改操作数对象之前排序的。"
按照C++ 03标准,以下两个语句都会导致未定义的行为:
正如您正确陈述的,G++指出以下警告:
warning: operation on ‘a’ may be undefined [-Wsequence-point]
注意,对于UB,答案可以是(a)、(b)、(c)、(d)以外的任何内容。理想情况下,测试问题中应该有一个"未定义行为"选项。但通常,准备问题的人只需在XYZ编译器中编译并提交问题。
这里有一篇相关的文章,解释了未定义的行为和序列点。
- +1虽然我会抱怨编译器实现的质量,如果它发出代码,在这种情况下让恶魔飞出我的鼻子。是的,这将是符合标准的,但它仍然很糟糕。
- EDCOX1〔0〕不是C++ 11中的UB。它是在C++ 03中的UB。
- 你不正确,因为C++ 11改变了这一点。
- @ DeadMG,对于C++和C++,我们仍然有不同的标签。
- "不,我们没有。我们有不同的C++和C++ 03的标签。
- 小狗:实际上,对于C++、C++ 03和C++ 11,我们有不同的标签。
a= ++a;B= B++;这些操作被认为是未定义的。每个编译器都可以随心所欲地工作。输出因编译器而异,审查员提出了问题。
我认为它是d),因为+a意味着增量a,然后执行操作,所以它就像执行a=11一样。B++意味着做这个操作,然后递增,所以你会给B=10赋值,但是如果B=11,它就会递增。
对纯粹主义者来说,这不是"先说什么,然后说什么",而是行为。我测试了它(使用Visual C++和G++),我的答案是正确的A=11和B=11。
- 这并不意味着"有事再有事"。
- 我不需要经验结果。现在几乎所有流行的编译器都表现出这种行为。但我想知道是否需要这样做,或者只是一个可以采用或不采用的回退方法。
- 不可能"测试"未定义的行为,因为它是未定义的,并且每个实现都可以做它想做的任何事情。(这与原始问题无关,顺便说一句)