左移 (<<) 是 C++11 中未定义行为的负整数吗?
Is left-shifting (<<) a negative integer undefined behavior in C++11?
左移是 C++11 中未定义行为的负面int
吗?
这里的相关标准段落来自5.8:
2/E1 <<E2 的值为 E1 左移 E2 位位置;空出 位为零填充。如果 E1 具有无符号类型,则 结果是 E1 × 2E2,比最大值多减模一 可在结果类型中表示。否则,如果 E1 具有有符号类型 和非负值,并且 E1×2E2 可在结果中表示 类型,然后是结果值;否则,行为为 定义。
让我感到困惑的部分是:
否则,如果 E1具有有符号类型和非负值,并且 E1×2E2 在结果类型中可表示,这就是结果值; 否则,行为是未定义的。
这是否应该被解释为左移任何负数是 UB? 或者这是否仅意味着如果您 LS 为负并且结果不适合结果类型,那么它就是 UB?
此外,前一条说:
1/换班操作员从左到右<<和>>组。 移位表达式: 加法表达 移位表达<<加法表达 移位表达>>加法表达
操作数应为整体或无作用域枚举类型,并且 执行整体促销。
结果的类型是提升的左操作数的类型。这 如果正确的操作数为负数或更大,则行为未定义 大于或等于提升的左操作数的长度(以位为单位)。
这明确表明对其中一个操作数使用负数是 UB。 如果是 UB 对另一个操作数使用负数,我希望在这里也能说清楚。
所以,底线是:
-1 << 1
未定义的行为?
@Angew提供了对标准语的伪法典解释,简洁地表达了一种可能的(可能的)有效解释。 其他人质疑这个问题是否真的是关于语言"行为未定义"的适用性,而不是我们(StackOverflow)使用短语"未定义的行为"。 这个编辑是为了进一步澄清我想问的问题。
@Angew对《标准》的解释是:
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;
这个问题真正归结为——实际上是正确的解释:
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;
}
?
旁注,从 psudocode 的角度来看待这个问题,我心中很清楚@Agnew的解释是正确的。
是的,我会说它是未定义的。如果我们将标准代码转换为伪代码:
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;
我想说的是,他们之所以明确使用右操作数而不是左操作数,是因为您引用的 paragrpah(带有右侧操作数大小写的参数)适用于左移位和右移位。
对于左侧操作数,规则不同。左移负数是未定义的,右移是实现定义的。
这是否应该被解释为左移任何负数是 UB?
是的,当给定任何负数时,行为是未定义的。仅当满足以下两个条件时,才会定义该行为:
- 数字为非负数
- E1 × 2E2 可在结果类型中表示
从字面上看,这就是"如果 E1 具有有符号类型和非负值,并且 E1×2E2 在结果类型中可表示,那么这就是结果值;否则,行为是未定义的,"他说:
if X and Y
then Z
else U
根据问题回答:
真正的问题是:
我们是否可以将术语"行为未定义"完全等同于术语"未定义的行为"。
按照目前的措辞,它的意思是"未定义的行为"。
个人对情况的评论
但我不相信这是作者的意图.
如果这是作者的意图,那么我们可能应该有一个注释来解释原因。但我更倾向于相信作者的意思是该操作的结果是未定义的,因为负数的表示没有明确定义由标准定义。如果没有为负数显式定义负数的表示形式,则移动位将导致未定义的值。
无论哪种方式,措辞(或解释)都需要收紧/扩展,以减少歧义。
- 如何反转整数参数包
- enum是C++中的宏变量还是整数变量
- 努力将整数转换为链表。不知道我在这里做错了什么
- 整数不会重复超过随机数
- 在C++中手动调整数组大小
- 检查输入是否不是整数或数字
- C++使用整数的压缩数组初始化对象
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 呼叫运营商<<临时
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 如何只允许用户输入正整数
- 如何在c++中从文本文件中逐行读取整数
- C++:如何循环通过向量中的整数元素
- 我可以信任表示整数的浮点或双精度来保持精度吗
- 序列化,没有库的整数,得到奇怪的结果
- 在一定长度后从数组中打印时缺少整数
- std::当在256字节边界上写入整数时,流的奇怪行为
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一