C按位移位:右操作数考虑用于隐式类型转换?

时间:2017-03-14 13:28:02

标签: c implicit-conversion bit-shift

gcc 4.8.4警告1u << 63ul​(假设64位long和32位int)并计算0。这是正确的(在转移之前没有从1u升级到1ul)?

ISO / IEC 9899:201x,6.3.1.8(通常的算术转换):“许多期望算术类型的操作数引起转换的运算符”; 6.5.7(按位移位运算符):“对每个操作数执行整数提升......”。

但我无法得出结论。哪些是“很多运营商”?据我所知,“整数提升”不属于宽度超过int的类型(我是否正确?),但标准没有明确说明按位移位的右操作数不考虑隐式类型转换。

2 个答案:

答案 0 :(得分:5)

每个操作都单独记录。例如,n1548§6.5.5“乘法运算符”¶3

  

通常的算术转换是在操作数上执行的。

§6.5.7“按位移位运算符”中省略了该短语。相反它说:

  

对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。 ...

由于按位移位运算符部分没有提及“通常的算术转换”,因此不会发生转换。

答案 1 :(得分:3)

“通常的算术转换”包括转换为浮点类型以及如何确定两个操作数的公共类型。

Bitshifts不对浮点类型进行操作,只对整数(约束,6.5.7p2)进行操作。与仅采用整数的其他二元运算符(例如,位和)不同,两个操作数不直接组合用于结果;没有要求具有该操作的通用类型。因此,每个操作数都是独立提升的(来自您的引文:“整数促销在每个操作数上执行 ”)。

阅读整段6.5.7p3明确指出:

  

对每个操作数执行整数提升。 结果的类型是提升的左操作数的类型。如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义。

注意强调句子,它澄清结果类型仅由左操作数确定。从那个和最后一句开始,右intunsigned int对于所有当前的实现来说,绰绰有余。 intINT_MAX)的最低上限是32767 - 远远超过任何实现的任何标准类型中的位数,即使我们考虑将来更宽的整数具有1024位以上。

另请注意,您的代码会调用未定义的行为,除非您的平台的unsigned int至少为64位(最后一句)。

编译器正确警告您的代码调用未定义的行为。警告是必需的,但您应该感到高兴。认真对待它!如果调用未定义的行为,程序的任何行为都是正确的。

如果您想要64位类型,请使用uint64_t。对于常量,使用宏UINt64_C(1),它生成一个整数常量至少 64位(uint_least64_t)。两者均由stdint.h提供。

关于您的其他问题:

  

从6.3.1.1p2开始:

     

如果int可以表示原始类型的所有值(由宽度限制,对于位字段),则该值将转换为int;否则,它将转换为unsigned int。这些被称为整数促销。 所有其他类型的整数促销都不会更改。