Automaticly filling bits in c with f while doing ">>" operation

I am having some fun with bit operations in C and i don’t get one thing. If i have char b = 0x6c, and then i have short y = 0x0000, and I do y=b; y = y >> 12;, why does it fill my y with ‘f’?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    short x = 0x0000;
    short y = 0x0000;
    char a = 0x00;
    char b = 0x00;
    char c = 0x00;

    a = 'a'; /// 61
    b = 'l'; /// 6c
    c = 'b'; /// 62

    x = a;
    x = x<<8;
    y = b;
    x = x + b;
    x = x >> 4;
    x = x << 4;

    y = y << 12;
    printf(" x + temp = %#06x y = %#06x\n", x, y);
return 0;
}

>Solution :

On a system with a 16-bit int, y << 12 results in undefined behaviour because y has a signed type, and 0x6C000 is too large to fit in an int.

On a system with a 32-bit (or larger) int and a 16-bit short, y = y << 12 results is implementation-defined or an implementation-defined signal is raised.

The second paragraph probably applies to you.

Also, %x expects an unsigned int, not a short. So your printf also results in undefined behaviour.

So the program exhibits implementation-defined and/or undefined behaviour.


Fixed:

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

int main( void ) {
   char a = 'a';  // 0x61
   char b = 'l';  // 0x6C
   char c = 'b';  // 0x62

   uint16_t x
      = ( ( (uint16_t)a & 0x00FF ) <<  8 )
      | ( ( (uint16_t)b & 0x00F0 ) <<  0 );

   uint16_t y
      = ( ( (uint16_t)b & 0x000F ) << 12 )
      | ( ( (uint16_t)c & 0x00FF ) <<  4 );

   // x = 6160 y = C620
   printf(" x = %04" PRIX16 " y = %04" PRIX16 "\n", x, y );

   return 0;
}

Demo on Compiler Explorer.

Leave a Reply