2

I am receiving some data from a socket.
After that, I want to print a single byte in the received char array.

Below is the code that I used:

char buf[100];                                                                
int i = 0;                                                                    
while (1)                                                                     
{                                                                             
    rc = recv(socket_fd, buf, sizeof(buf), 0);                                  

    if (rc > 0)                                                                 
    {                                                                           
        printf("Pos1 = %x.\n", (char)buf[17]);   
        printf("Pos2 = %x.\n", (char)buf[22]);   
    }     
}

But this prints out 4 bytes. If I typecast the characters to unsigned char, then single byte is printed. So what is the difference between these two typecasts, that is resulting in different number of bytes being printed.

Output:

Pos1 = 1

Pos2 = ffffff83
mrogal.ski
  • 5,828
  • 1
  • 21
  • 30

4 Answers4

2

If you want to print just 2 nibbles, use:

printf("Pos1 = %02x.\n", (unsigned)(unsigned char)buf[17]);
/*              ^^                           */
/* Print 2 nibbles with 0 prefix if required */

On some systems, char may behave as signed char and you would see ff prepended to show negative numbers. So you must cast your buf[i] to unsigned char on such systems. Second unsigned is used to match the type of argument with specifier %x

Working example

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
1

IF you go to a reference on the C stdio lib for printf

Specifier 'x' prints an Unsigned hexadecimal integer.

So first of all, the print function is going to expect an integer value.

In your example you are casting to a signed char.

What appears to be going on, is when you cast your variable to a signed char, and if that value exceeds 127 (0X7F), the signed bit which is set, will be extended to a 4-Byte integer entity. On the otherhand, if the value is positive (0 to 127), the output (though technically an unsigned int value) will be the same as the unsigned char cast.

For example 128 (0x80) will appear as FFFFFF80 if you cast as a Char and 80 when cast as an unsigned char.

127 on the otherhand will be displayed as 7F with either cast.

Therefore, when using printf the variable type you want to print should match the specifier type.

Dave S
  • 973
  • 9
  • 17
1

So what is the difference between these two typecasts, that is resulting in different number of bytes?

Each input argument passed to function printf is "extended" to 4 or 8 bytes (depending on its type) before being pushed into the stack.

When you pass an input argument whose type is signed, the sign-bit is "preserved".

For example, signed char 0x89 is extended to signed int 0xFFFFFF89.

While unsigned char 0x89 is extended to unsigned int 0x00000089.


Please note that the answer above is platform-dependent.

I've assumed that on your platform:

  • CHAR_BIT is 8
  • sizeof int is 4
  • sizeof double is 8

AFAIK with regards to printf input arguments:

  • An integral argument smaller than int is extended to int
  • A non-integral argument smaller than double is extended to double
barak manos
  • 29,648
  • 10
  • 62
  • 114
0

Tell printf that you are passing in half of the half of an unsigned int by doing

printf("Pos1 = %hhx.\n", (unsigned char) buf[17]);
alk
  • 69,737
  • 10
  • 105
  • 255