Home > Software design >  strange behavior of left shifting with char variable in C
strange behavior of left shifting with char variable in C

Time:11-19

I am trying to left shifting with char variable. It's giving strange output. According to C standard, Range of signed char is 127 to -128, So I output will be -128 of following program but it's printing 640.

#include <stdio.h>

int main()
{
    char c = 5;
    
    printf("%d\n", (c << 7));
    
    return 0;
}

Is it undefined behavior?

Online compiler : Wandbox

CodePudding user response:

Actually it is implicitly type casted to int type. That's why you are getting unexpected output.

Type cast explicitly to get expected output.

printf("%d\n", (char) (c << 7));

Or

You can do this

c = (char)(c<< 7);

CodePudding user response:

1. "...but it's printing 640..." ?

Since the 8-bit binary number for 5 is 00000101, c << 7 results in a 32-bit binary number 0...(other 20 0s)...01010000000, which is 640 in decimal.

2. "...Is it undefined behavior..." ?

No, the behavior is defined by the standard. This behavior consists of two major processes, one is Bitwise Shift Operators, and the other is Integer Promotions.

For Bitwise Shift Operators, in C99 6.5.7 p3:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand.

For Integer Promotions, in C99 6.3.1.1 p2:

An object or expression with an integer type whose integer conversion rank is less than or equal to the rank of int and unsigned int.
If an int can represent all values of the original type, the value is converted to an int;

Accoding to these definitions, the result of c << 7 would eventually be an int type number 640, whose bit pattern is 0...(other 20 0s)...01010000000.

One workaround is doing as what @msc suggested, that is, (char) c << 7, which has the effect that roughly described as follows:

#1: (char)c<<7  

   ——————> 0...(other 20 0s)...01010000000  
   ——————> (Promotion & Truncation happened)
   ——————> 10000000   

#2: %d

   ——————> (Promotion & Sign Extension happened)
   ——————> 1...(other 20 1s)...11110000000  
  
#3: printf  

   ——————> 1...(other 20 1s)...11110000000   ->   -128
  • Related