Question

Bitwise operators have never been my forte. I'm wondering when explicit casts are necessary when using bit-shifts.

For example, is i&1 == i%2 guaranteed to be true whenever i is an unsigned integer type, e.g. char, unsigned, uint64_t etc.? I think the question is whether the 1 in i&1 is implicitly casted to a type of width sizeof(i).

As a second example, if I do a i = 1<<myshift, do I need to first explicitly cast the 1 to a datatype sufficiently wide to store the shifted result, e.g.: i = (uint64_t)1<<myshift?

Is the type of myshift in the second example irrelevant as long it's unsigned?


I think the answers to these are yes, yes, and yes. The second example in particular can be quickly checked. But does anyone have a good reference for this stuff? Links-to / quotes-from the C standard would be hugely helpful.

Was it helpful?

Solution

1 Yes. The odd bit is the least significant - the one that is on in '1', whatever representation you will choose.

according to the standard:

Constraints

2 Each of the operands shall have integer type.

Semantics

3 The usual arithmetic conversions are performed on the operands.

4 The result of the binary & operator is the bitwise AND of the operands (that is, each bit in the result is set if and only if each of the corresponding bits in the converted operands is set).".

2 Yes, you do have to do this if you need more than sizeof(int) bytes (which will probably be 4).

3 Yes. The standard again:

Constraints

2 Each of the operands shall have integer type.

Semantics

3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1*2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1*2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top