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.