71

I'm very new to dealing with bits and have got stuck on the following warning when compiling:

 7: warning: left shift count >= width of type

My line 7 looks like this

unsigned long int x = 1 << 32;

This would make sense if the size of long on my system was 32 bits. However, sizeof(long) returns 8 and CHAR_BIT is defined as 8 suggesting that long should be 8x8 = 64 bits long.

What am I missing here? Are sizeof and CHAR_BIT inaccurate or have I misunderstood something fundamental?

Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
Rupert Madden-Abbott
  • 12,899
  • 14
  • 59
  • 74

6 Answers6

116

long may be a 64-bit type, but 1 is still an int. You need to make 1 a long int using the L suffix:

unsigned long x = 1UL << 32;

(You should also make it unsigned using the U suffix as I've shown, to avoid the issues of left shifting a signed integer. There's no problem when a long is 64 bits wide and you shift by 32 bits, but it would be a problem if you shifted 63 bits)

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • Would `unsigned long x = 1; x <<= 32;` work, out of interest? – Niet the Dark Absol Nov 17 '10 at 03:53
  • 1
    @Kolink: Yes, that would have the same effect, as would `(unsigned long)1 << 32` The left operand just has to be an `unsigned long`. The `UL` suffix is just the most straightforward way to accomplish that. – James McNellis Nov 17 '10 at 04:03
  • @James McNellis: What's the *issues of __left__ shifting a signed integer*? I only know that ***right*** shifting a signed integer may leads to different result with different compilers. – pynexj Mar 18 '13 at 05:34
  • @whjm: It may overflow. Signed integer overflow is undefined behavior. – Siyuan Ren Mar 10 '14 at 09:46
  • 3
    @whjm: I just referred to the C99 standard and found following: _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**._ – pynexj Mar 17 '14 at 05:33
  • As it's "only" a warning, what should we assume when it will be run? Will `1 << 32` be just the same as `1UL << 32`? Undefined behavior? – Matthieu May 18 '17 at 12:10
  • @Matthieu since 1 is an `int`, `1 << 32` simply shifts 1 out of `int` range, making the result 0 – Somebody Jun 27 '22 at 22:02
20

unsigned long is 32 bit or 64 bit which depends on your system. unsigned long long is always 64 bit. You should do it as follows:

unsigned long long x = 1ULL << 32
Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
tznza
  • 201
  • 2
  • 2
3

The accepted solution is fine for [constant]ULL<<32 but no good for existing variables - e.g. [variable]<<32. The complete solution for variables is: ((unsigned long long)[variable]<<32). Aside: My personal opinion of this warning is that it is totally unnecessary in the first place. The compiler can see what the receiving data type is and knows the width of the parameters from the definitions in headers or constant values. I believe Apple could make the clang compiler a little more intelligent than it is regarding this warning.

VectorVictor
  • 693
  • 1
  • 10
  • 20
1

unsigned long x = 1UL << 31;

Not show the error message. Because before you specify the 32, is not true because only limited to 0-31.

Muthuraman
  • 143
  • 2
  • 9
1

You can't shift a value to its max bit

int x;         // let int be 4 bytes so max bits : 32 
x <<= 32; 

So, this generates the warning

left shift count >= width of type (i.e type = int = 32 )

Pavan Manjunath
  • 27,404
  • 12
  • 99
  • 125
  • Your wording is wrong. You **can** shift a `1` to the most significant bit of its type, if it's `unsigned` or if it's `signed` and has `INT_MIN == 1 << width - 1`. It's shifting *beyond* that highest bit that can cause problems. – underscore_d Oct 30 '17 at 23:54
  • @underscore_d no you can't try it (on an unsigned type). `int main(){ unsigned int x = 1 << 32; unsigned int y = 32; unsigned int z = 1 << y; printf("x:%d, z: %d\n", x, z); }` – Evan Carroll Sep 18 '18 at 21:27
  • @EvanCarroll I think we are just all arguing at cross purposes about what "to its max bit" means, i.e. whether "to" means "by" and/or "max" means "most significant"... I was speaking in terms of shifting **to** the **most significant** bit, which is fine. What you and Vipul said, `1 << 32` i.e. `1 << sizeof(T) * CHAR_BIT`, shits the `1` **one bit beyond that**, which is a different matter. – underscore_d Sep 18 '18 at 21:32
  • I fixed the typo of "byte". And you're still not getting it! Indexing bits from 1 at the least significant place: `1` is the 1st, least significant bit of a 32-bit type (which, by the way, `unsigned int` is not necessarily). To shift that to the most significant bit, i.e. the 32nd bit, we shift left by **31**, so we are then at 1 + 31 = the 32nd, most significant bit. I was quibbling with the wording and saying that doing this, `1 << 31` in a 32-bit type, is fine. I'm not saying to do `1 << 32` – underscore_d Sep 18 '18 at 21:37
-2

You can use something like that:

unsigned long x = 1;
x = x << 32;
Mateusz Piotrowski
  • 8,029
  • 10
  • 53
  • 79
John
  • 67
  • 1
  • 4
  • What? Why? How is this any different from the original code? It is still invalid. Any barely competent compiler would realise this and still warn. And even if it didn't, the code would still be ill-formed and have undefined behaviour if compiled. – underscore_d Oct 23 '18 at 21:48