Joh*_*ing 13 c++ language-lawyer c++11
int在C++ 11中左移一个负的未定义行为?
这里的相关标准段落来自5.8:
2/E1 << E2的值是E1左移E2位的位置; 空位是零填充的.如果E1具有无符号类型,则结果的值为E1×2E2,比结果类型中可表示的最大值减少一个模数.否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2E2,那么这就是结果值; 否则,行为未定义.
令我困惑的部分是:
否则,如果E1具有有符号类型和非负值,并且在结果类型中可以表示E1×2E2,那么这就是结果值; 否则,行为未定义.
这应该被解释为左移任何负数是UB吗?或者它只是意味着如果你的LS为负数且结果不适合结果类型,那么它是UB?
而且,前面的条款说:
1 /移位运算符<<和>>组从左到右.shift-expression:additive-expression shift-expression << additive-expression shift-expression >> additive-expression
操作数应为整数或无范围的枚举类型,并执行整体促销.
结果的类型是提升的左操作数的类型.如果右操作数为负数,或者大于或等于提升左操作数的位长度,则行为未定义.
这使得明确表示对其中一个操作数使用负数是UB.如果UB对另一个操作数使用负数,我希望在这里也要明确.
所以,底线是:
-1 << 1
Run Code Online (Sandbox Code Playgroud)
未定义的行为?
@Angew 提供了对Standardese的psudocode解释,它简洁地表达了一种可能(可能)有效的解释.其他人质疑这个问题是否真的与"行为未定义"的语言的适用性相比,而我们(StackOverflow)使用了"未定义行为"这一短语.这个编辑是为了提供一些我想要问的更多说明.
@Angew对Standardese的解释是:
if (typeof(E1) == unsigned integral)
value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
value = E1 * 2^E2;
else
value = undefined;
Run Code Online (Sandbox Code Playgroud)
这个问题真正归结为这个 - 实际上是正确的解释:
value = E1 left-shift-by (E2)
switch (typeof(E1))
{
case unsigned integral :
value = E1 * 2^E2 % blah blah;
break;
case signed integral :
if (E1 >= 0)
{
if (representable(E1 * 2^E2))
{
value = E1 * 2^E2;
}
else
{
value = undefined;
}
}
break;
}
Run Code Online (Sandbox Code Playgroud)
?
Sidenote,从psudocode的角度来看这个问题让我很清楚@Agnew的解释是正确的.
是的,我会说这是未定义的.如果我们将standardese翻译为伪代码:
if (typeof(E1) == unsigned integral)
value = E1 * 2^E2 % blah blah;
else if (typeof(E1) == signed integral && E1 >= 0 && representable(E1 * 2^E2))
value = E1 * 2^E2;
else
value = undefined;
Run Code Online (Sandbox Code Playgroud)
我会说他们明确右手操作数而不是左手操作数的原因是你引用的paragrpah(带有右手操作数的情况)适用于左右移位.
对于左手操作数,裁决有所不同.左移一个负数是未定义的,右移它是实现定义的.
这应该被解释为左移任何负数是UB吗?
是的,当给出任何负数时,行为是不确定的.仅当满足以下两个条件时才会定义行为:
这实际上是"如果E1具有有符号类型和非负值,并且E1×2 E2在结果类型中是可表示的,那么这就是结果值;否则,行为是未定义的",说:
if X and Y
then Z
else U
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4210 次 |
| 最近记录: |