Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc weird behaviour with bitwise operations

#include <stdint.h>
#include <stdio.h>

int main(){
    uint64_t number = 0;

    for (uint8_t i = 0; i<4; i++){
        number |= 0xFF<<(8*i);
        printf("%032lb %lu\n",number,number);
    }
    
    return 0;
}

I wrote this function to debug my study project and i can't understand why i am getting this output:

00000000000000000000000011111111 255
00000000000000001111111111111111 65535
00000000111111111111111111111111 16777215
1111111111111111111111111111111111111111111111111111111111111111 18446744073709551615

Because i was expecting:

00000000000000000000000011111111 255
00000000000000001111111111111111 65535
00000000111111111111111111111111 16777215
11111111111111111111111111111111 4294967295
like image 656
Евгений Шпиц Avatar asked Sep 11 '25 20:09

Евгений Шпиц


1 Answers

Integer constants ("literals") like 0xFF have a type too. Hex literals are generally of type int, unless they can only fit in an unsigned int.

This means that at the last lap of your loop, you invoke undefined behavior (anything can happen) by doing 0xFF << 24. This is shifting data into the sign bit of the int 0xFF.

One possible (not guaranteed) outcome of that undefined behavior is that the sign bit will get set and then later when converted to uint64_t, the operand gets sign extended from 0xFF00000 = -16777216 into 0xFFFFFFFFFF00000. And when you bitwise OR everything together you end up with "all ones".

Solution: always make sure the left operand of shifts is an unsigned type of the same size as int or larger. In this case change to 0xFFu to enforce unsigned int.

like image 50
Lundin Avatar answered Sep 13 '25 08:09

Lundin