简体   繁体   中英

Left shifts and right shifts on boolean

I am trying to understand exaclty how integral promotion works with arithmetic shifts operators. Particularly, I would like to know, which values of a, b, c, d, e, f, g, h are exactly defined according to the C++14 standard, and which ones can depend on the platform/hardware/compiler (assuming that 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;

From [expr.shift]:

The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the length in bits of the promoted left operand.

The result type of shifting a bool is always int , regardless of what's on the right hand side. We're never shifting by at least 32 or by a negative number, so we're ok there on all accounts.

For the left-shifts (E1 << E2):

Otherwise, if E1 has a signed type and non-negative value, and E1×2 E2 is representable in the corresponding unsigned type of the result type, then that value, converted to the result type, is the resulting value; otherwise, the behavior is undefined.

1×2 31 is representable by unsigned int , and that's the largest left-shift we're doing, so we're ok there on all accounts too.

For the right-shifts (E1 >> E2):

If E1 has a signed type and a negative value, the resulting value is implementation-defined.

E1 is never negative, so we're ok there too! No undefined or implementation-defined behavior anywhere.

Following is mainly a complement to Barry's answer, that clearly explains the rules for left and right shifting.

At least fo C++11, the integral promotion of a bool gives 0 for false and 1 for true : 4.5 Integral promotions [conv.prom] § 6

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

So in original examples, b , d , f and h will all get a 0 value, a and c both get a 8 value: only perfectly defined behaviour until here.

But e and g will receive the unsigned value 0x80000000 , so it would be fine if you affected it to an unsigned int variable, but you are using signed 32 bits integers. So you get an integral conversion : 4.7 Integral conversions [conv.integral] §3

If the destination type is signed, the value is unchanged if it can be represented in the destination type; otherwise, the value is implementation-defined.

And unsigned 0x80000000 is not representable in a signed 64 bits integer so the result is implementation defined for e and g .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM