Home > database >  C language printf function and output problem
C language printf function and output problem

Time:11-03

I need help solving this problem in my mind, so if anyone had a similar problem it would help me a lot.

signed char c=0x10;
printf("%x", c<<0x4|c>>0x4); 

Why output is 101?

CodePudding user response:

In expressions with shift operators the integer promotions are applied to the each operand and in this particular case to the object c.

From the C Standard (6.5.7 Bitwise shift operators)

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

So after the integer promotions it will be represented like (provided that sizeof( int ) is equal to 4)

00000010

This expression

c<<0x4

produces the following value

00000100

and this expression

c>>0x4

produces the following value

00000001

The bitwise operator | yields

00000100
|
00000001
========
00000101

The result is outputted without leading zeroes as

101

That is the function printf outputs the resulted value of the type int as an object of the type unsigned int because the resulted value can be represented in an object of the type unsigned int.

To get the expected by you result use the length modifier hh as for example

printf("%#hhx", c<<0x4|c>>0x4);

In this case the program output will be

0x1

CodePudding user response:

signed char c=0x10;
printf("%x", c<<0x4|c>>0x4); 

Why output is 101?

Because c<<4==0x100 and c>>4==0x01. ORing them together results in 0x101

Important here is that there is implicit type promotion to int before applying the << operator.

If you expected to get the nibbles swapped, you need to add some masking:

(c&0x0F)<<4 | (c&0xF0)>>4

CodePudding user response:

In most expressions, a signed char is automatically promoted to an int, which is at least 16 bits. So c<<0x4 is evaluated with at least 16 bits of data; it does not lose the high bits as it would if the result were limited to eight bits.

So c << 0x4 shifts 0001 0000 by four bits, producing 0001 0000 0000. And c >> 0x4 of course produces 0001. ORing those together produces 0001 0000 0001, which is 10116.

You can remove the high bits in various ways. One is to explicitly convert the subexpression to the desired type: (signed char) (c << 0x4) | c >> 0x4. Note this has a problem in that the conversion of an out-of-range value to a signed type is implementation-defined. It is usually preferable to use unsigned types when working with bits in this way, as then the results are fully defined by the C standard.

Another method is to use AND with a “mask” to select the desired bits: (c << 0x4 | c >> 0x4) & 0xFF.

  • Related