28

I have the following C code which works:

int ex(unsigned int x) {
    int mask  = 0x55555555;
    int a = ((x >> 0) & mask );
    return a + ((x >> 1) & mask );
}

However, when I expand it to this, I get a different result:

int ex(unsigned int x) {
    int mask  = 0x55555555;
    int a = ((x >> 0) & mask );
    int b = ((x >> 1) & mask );
    return a + b;
}

What is the reason for this difference?

EDIT: Note, I'm compiling this for 32bit.

alk
  • 66,653
  • 10
  • 83
  • 219
cdignam
  • 1,158
  • 1
  • 11
  • 16
  • 15
    Always use unsigned types for bit operations. – John Sep 22 '17 at 17:01
  • 2
    Just out of curiosity, on what platform + compiler does this actually fail for you, and how? Because [I see no difference on GCC / x86-32](https://tio.run/##tVDLboMwELznK7ZUqYyACBL11MIntD/Qi7F5rAomwrhFqvj1ujaYhFx6yx4se2dmZ9YsqhjT@hEFaxQv4FUOHLtDne1QDFCMCVFCYiUKDrYx@vCzA1P20VL5CZBCPD67erlg1PQJGSHLIPbhaeH6C94Xg@qFoQQrJdlSJmd9vIO1xfMrnvwTLV@TtBQFkK8O@ZrgJhfaGIuad46wjWL/EP1wtrVLobOaOSUQCg8p5P5GaevcG31JPKveK@Ocwp5bph1xaXwILwQMgc5nvpm8WSa5dqf5NsF3jU0BJAjQjoyd7qwGSby3DlqULR1YDWWnBD94t59jlp20/mVlQyupo/Z01NH76Q8) (unless I add `-ftrapv`, which makes the second code crash due to overflow as expected). – Ilmari Karonen Sep 22 '17 at 17:42
  • (The second version does, of course, invoke undefined behavior if the addition overflows. But at a glance it seems to me that, to actually get the second function to behave differently from the first in practice, you'd probably either need to find a platform where signed integer addition doesn't wrap by default, or else somehow get the compiler to inline the function and then make some unexpected optimization based on the assumption that the addition won't overflow. Which presumably would depend strongly on the actual calling code; hence my curiosity.) – Ilmari Karonen Sep 22 '17 at 17:55
  • This is a simplified snippet of code from a larger function. You're right, on my platform, these two snippets behave identically, but in the full function, the implicit type conversion issue pops up. – cdignam Sep 22 '17 at 18:37
  • What do you mean with "different results"? What are the results, with what values passed as `x`? – user5329483 Sep 29 '17 at 17:08

1 Answers1

39

What is the reason for this difference?

The 1st snippet returns the result of adding two unsigneds with the result being (implicitly) converted to an int.

The 2nd snippet returns the result of adding two ints .


More on "The Usual Arithmetic Conversions":

alk
  • 66,653
  • 10
  • 83
  • 219