2

I am trying to add in a left-wise operator to replace the following:

unsigned long bitmask = 0b10000000000000000000000000000000;
printf("%lu\n", bitmask);

unsigned long bitmask2 = (1 << 31)-1;
printf("%lu\n", bitmask2);

However, the closest I'm able to get is -1. If I try doing (1 << 31), it looks like I get an overflow or something. What would be the proper way to do this?

# in the python shell
>>> 0b10000000000000000000000000000000
2147483648

>>> 1<<31
2147483648

>>> 0b10000000000000000000000000000000 == 1<<31
True
  • 1
    Possible duplicate of [Calculating maximum int value in C program (1 << 31) - 1](https://stackoverflow.com/questions/17019187/calculating-maximum-int-value-in-c-program-1-31-1) – phuclv Sep 04 '19 at 04:15
  • [bit shifting with unsigned long type produces wrong results](https://stackoverflow.com/q/31744305/995714), [How does 1 left shift by 31 (1 << 31) work to get maximum int value?](https://stackoverflow.com/q/39206842/995714), [Is unsigned long int correct for this operation?](https://stackoverflow.com/q/35119136/995714), [C++ bitwise left shift by 32](https://stackoverflow.com/q/40951434/995714) – phuclv Sep 04 '19 at 04:17

3 Answers3

3

Since the type of the result of your shift is unsigned long, you should start with an unsigned long constant:

unsigned long bitmask2 = (1UL << 31) - 1;
1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
1

Change

unsigned long bitmask2 = (1 << 31)-1;

to something like

unsigned long bitmask2 = (1UL << 31);

instead

The overflow was caused by you are bitwise shifting 31 places for 1 which exceed the boundary of a signed int. Please note that 1 is a signed int literal.

Adrian Shum
  • 38,812
  • 10
  • 83
  • 131
0

All integer constants like 1 have a type, in this case int. An int is signed and therefore has 31 data bits and 1 sign bit. You cannot left shift data into this sign bit - 1<<31 is a severe undefined behavior bug.

As a rule of thumb, never mix signed operands with bitwise operators. You can fix the bug by adding a 'u' suffix to the integer constant: 1u << 31. Now the type is unsigned int instead, 32 data bits.

Please note that the resulting type of a shift operation is that of the left operand. So there is no need to write for example 1u << 31u.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • There seems to be quite some incorrect information: 1. in C/C++ `int` is not necessary to be 32-bit 2. as the variable is `unsigned long`, it is a better idea to make sure the result type of the shift operation is also `unsigned long`. That's why in other answers, we are suggesting `1UL` instead of `1U`. 3. I believe the resulting type is determined by the `left operand`. For binary operators, it should be determined by type promotion, for which will promote to `unsigned long` if either side is `unsigned long`. Which means, it will also work to write `1 << 31UL` (though looks funny) – Adrian Shum Sep 05 '19 at 06:43
  • @AdrianShum In case `int` isn't 32 bits, then the OP's question doesn't make any sense, now does it? `unsigned long` is irrelevant, because it is either 32 or 64 bits and in either case it doesn't affect the shift operation the slightest. Using `ul` instead of `u` doesn't add anything except fussiness. – Lundin Sep 05 '19 at 06:56
  • @AdrianShum Your understanding of type promotion for the `<<` operator is incorrect and `1 << 31UL` will _not_ work but invoke undefined behavior. As mentioned in the answer, the shift operators are a special case and the usual arithmetic conversions do not apply. Instead, both operands are integer promoted and the result is the type of the promoted left operand, always. I would appreciate if you don't downvote my answer because _you_ don't understand how type promotion works. – Lundin Sep 05 '19 at 06:57
  • @AdrianShum To spell it out to you, C17 6.5.7 Bitwise shift operators **"The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand."** – Lundin Sep 05 '19 at 06:58
  • 1. you are right that on OP's platform, `int` is 32 bit, there is no doubt. What I meant inaccurate is the statement `An int is signed and therefore has 31 data bits and 1 sign bit.`. imho it is overly simplified to say `int` has certain width. It could be better to say "on your platform". 2. it is totally possible to `unsigned int` with 16 bit (though not on OP's platform). Only `long` is guaranteed to be 32 bit or wider. – Adrian Shum Sep 05 '19 at 07:20
  • 3. You are right, I misunderstood the standard here :) I mistakenly though it is doing type promotion, but turned out it is just integer promotion. Thanks for pointing out – Adrian Shum Sep 05 '19 at 07:43