-2

i have this simple code, why does it return this random char?

#include <stdio.h>

int main()
{
    char c = '1';
     printf("%c\n",c);
    c = c << 2;

    printf("%c\n",c);

    return 0;
}



1

? (some random character)

why didn't it return 2?

mike
  • 767
  • 2
  • 10
  • 18
  • check your answer here http://stackoverflow.com/questions/1097130/in-c-left-shift-char-0xff-by-8-and-cast-it-to-int – venki Aug 03 '15 at 11:14

4 Answers4

3

Because '1' and 1 are not the same thing. '1' is a character literal that represents the number 1, the underlying value that represents the character '1' depends on the charset in use.

For example, in ASCII the character 1 is represented by the decimal value 49 (hexadecimal 0x31). So assuming ASCII, c = c << 2 assigns the value 196 (multiplies by 4) to c. If a char is signed and is 8 bits long (which is often the case) this will overflow and invoke undefined behavior.

If you want it to print 1 and 2 you should a) multiply by 2 instead of 4 (that is, shift 1 instead of 2), and b) store the numeric value instead of its representation (but of course, then you need to adjust it when printing):

int main()
{
    char c = 1;
    printf("%c\n", c+'0');
    c = c << 1;

    printf("%c\n", c+'0');

    return 0;
}
Filipe Gonçalves
  • 20,783
  • 6
  • 53
  • 70
  • There is no standardised character set for which `'0'` through `'9'` are not consecutive. It's a different story for letters though. – Peter Aug 03 '15 at 11:29
  • in C `'0'` to `'9'` must be consecutive http://stackoverflow.com/q/9416926/995714 – phuclv Aug 03 '15 at 11:39
1

The integer '1' has ASCII value 49. So the left shift on it, c<<2 produces 196 which is then assigned back to char variable c. It would overflow char if char is signed. This is possibly what happens on your platform, printing random character.

Not sure why you expect the bit shifting to produce 2. If you want the char '2' then simply add 1 to c.

c = c+1; 
P.P
  • 117,907
  • 20
  • 175
  • 238
  • "The C standard doesn't guarantee the '1' +1 would yield '2'" - yes it does. Section 5.2.1, (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf): "In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous" – Andrew Henle Aug 03 '15 at 11:22
  • http://stackoverflow.com/q/9416926/995714 `'0'` through `'9'` are guaranteed to be contiguous be C standard – phuclv Aug 03 '15 at 11:41
  • @AndrewHenle Sorry. I was confused it with `a` .. `z`. – P.P Aug 03 '15 at 11:51
1

Shifting left once multiplies a value by 2. Shifting left twice multiplies a value by 4. So in the first place, you certainly won't get the answer 2 even when the code is correct.

Now to the detail. You are using the print format %c which shows the value as a character. The ASCII code for '1' is 49. If you multiply this by 2 you get 98 which is the ASCII code for 'b'.

You should make the adjustment for ASCII before and after the computation:

#include <stdio.h>

int main(void)
{
    char c = '1';
    printf("%c\n", c);
    c = c - '0';                // ASCII adjustment
    c = c << 1;                 // double
    c = c + '0';                // ASCII adjustment
    printf("%c\n", c);
    return 0;
}

Program output:

1
2
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
1

It seems like you are trying to access the next character value of c. When you executed the statement c = c << 2

What Actually Happened:

  • Character was first converted to integer (it's own ASCII value)
  • 49 (ASCII value of 1 is 49) is then two times multiplied by 2 (c << 2 is basically the left shift by 2, first left shift made the original value multiplied by 2, second left shift made the result multiplied by two)
  • Hence resultant value is 196 not 2 that stored in c after typecasting.

What You Should Do:

You should simply add 1 to the variable c, because it will convert the character to its ASCII and then will add 1 to it i.e. character c has the ASCII value 49, when it will be incremented, the new value will be 50 which is equivalent to 2 when converted to character. Try this:

c = (int)c + 1;    //By force conversion from character to integer to get the ASCII value

Hope this helps.

Itban Saeed
  • 1,660
  • 5
  • 25
  • 38