1

I am basically trying to do the following:

c[i] = ((number_to_store << pos) & 0xFF00000000) >> 32;

But this stores 0 in c[i] something not expected. The following works like a charm:

c[i] = ((number_to_store << pos) & 0xFF000000) >> 24;

I am 99% sure the error has something to do with the fact all my variables are unsigned int but here I am requesting 40 bits space.

Can someone please explain the differences between less than or equal to 32 bit and more than 32 bit number, when it's about bit manipulation?

edit: This also gives me 0:

cout << ((((unsigned long)number_to_store << (unsigned long)pos) & (unsigned long)0xFF00000000) >> 32) << endl;

edit 2: The following works:

cout << ((((unsigned long long)number_to_store << (unsigned long long)pos) & (unsigned long long)0xFF00000000) >> 32) << endl;

Lesson learned: never expect long to be larger than int

Luka
  • 1,761
  • 2
  • 19
  • 30
  • No different, you just have more space to deal with. – Richard J. Ross III Jan 18 '14 at 18:23
  • Is there any reason to add `UL` at the end of `0xFF00000000` – Luka Jan 18 '14 at 18:26
  • Beware of using shifts instead of a divide, at certain sizes... it's [undefined behavior](http://blogs.msdn.com/b/larryosterman/archive/2011/02/11/the-case-of-the-inconsistent-right-shift-results.aspx) on certain platforms. Most notably x86 and x86-64 do weird things if you shift more than 31 bits using an `int`. – Mgetz Jan 18 '14 at 18:31
  • Thanks for pointing this out, can you please explain it? – Luka Jan 18 '14 at 18:33
  • @Luka basically with a 32 bit int it is undefined behavior to shift more than 31 bits. Using a 64bit type it is UB to shift more than 63bits. So `c[i]` should be of the type `long long` to be safe to shift 32 bits. – Mgetz Jan 18 '14 at 18:34
  • OK, I see, so I have to use a long long, right? also, what UB is? – Luka Jan 18 '14 at 18:36
  • @Luka undefined behavior – Mgetz Jan 18 '14 at 18:36
  • @Mgetz: If I do this: `c[i] = (((unsigned long long)number_to_store << pos) & 0xFF00000000) >> 32;` and leave the type of `c[i]` to unsigned char, I am safe? – Luka Jan 18 '14 at 18:38

1 Answers1

1

An unsigned int is 32 bits, if you shift it by 32 bits it will become 0. As you found out, in order to keep bits that are shifted left in your first shift, you must declare the number_to_store as unsigned long long which is 64 bits.

Eric Fortin
  • 7,533
  • 2
  • 25
  • 33
  • why long exists if on msvc is 4 bytes, and int is also 4 bytes? why they try to confuse people? – Luka Jan 18 '14 at 18:30
  • It is compiler defined as the standard does not define size of integral types. This question might shed some light on why MSVC defines int the same size as long: http://stackoverflow.com/questions/18353168/why-long-int-has-same-size-as-int-are-this-modifier-works-at-all – Eric Fortin Jan 18 '14 at 18:35
  • @EricFortin it won't necessarily go to zero see the link to Larry Osterman's blog in my comment on the question above. Shifting by more than 31bits on a 32bit type is undefined behavior. – Mgetz Jan 18 '14 at 18:38