我试图理解exaclty积分推广如何与算术移位运算符一起工作。特别是,我想知道,a, b, c, d, e, f, g, h
的哪些值是根据C ++ 14标准准确定义的,哪些值可以依赖于平台/硬件/编译器(假设sizeof(int) == 4
)。
int a = true << 3;
int b = true >> 3;
int c = true << 3U;
int d = true >> 3U;
int e = true << 31;
int f = true >> 31;
int g = true << 31U;
int h = true >> 31U;
答案 0 :(得分:2)
来自[expr.shift]:
结果的类型是提升的左操作数的类型。如果右操作数,则行为未定义 是负的,或大于或等于提升的左操作数的位数。
bool
的结果类型始终为int
,无论右侧是什么。我们永远不会偏移至少32或负数,所以我们在所有帐户上都可以。
对于左移(E1 <&lt;&lt; E2):
否则,如果E1具有带符号类型且非负值,则E1×2 E2 可表示 在结果类型的相应无符号类型中,那么转换为结果类型的值是 结果价值;否则,行为未定义。
1×2 31 可由unsigned int
表示,这是我们正在进行的最大左移,所以我们在所有帐户上也都可以。
对于右移(E1>&gt; E2):
如果E1具有有符号类型和负值,则结果值是实现定义的。
E1永远不会消极,所以我们也可以!在任何地方都没有未定义或实现定义的行为。
答案 1 :(得分:0)
以下主要是对巴里答案的补充,这清楚地解释了左右移动的规则。
至少对于C ++ 11,bool的整体提升为false
提供0,为true
提供1:4.5整数提升[conv.prom]§6
bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1。
因此,在原始示例中,b
,d
,f
和h
都将获得0值,a
和c
获得8
值:直到此处才有完美定义的行为。
但e
和g
将收到无符号值0x80000000
,因此如果您将其影响到unsigned int变量,但使用带符号的32位整数,则可以。所以你得到积分转换:4.7积分转换[conv.integral]§3
如果目标类型已签名,则该值如果可以在目标类型中表示,则不会更改;否则,该值是实现定义的。
无符号0x80000000在带符号的64位整数中无法表示,因此e
和g
的结果为实现已定义。