how to make the output just "8a" instead of "ffffff8a" ?

+9 votes
asked Sep 11 by Ria Salangsang (220 points)

char c = -118;
    printf("%x\n",c);

ffffff8a

i just wanna make the output "8a" and not "ffffff8a"

3 Answers

–1 vote
answered Sep 11 by Rahul Choubey (460 points)

Negative numbers are represented with a 1 instead of a 0 at the beginning of the number in binary storage. Why would a char variable be set to a negative number, anyway?

Overflowing the integer is the answer. Add 256 to get only the last two digits(16 ^ n for the last n hex digits of a negative number given solid fs on the left)

char c = -118;
printf("%x\n", c + 256);

commented Sep 14 by Peter Minarik (7,830 points)
"Why would a char variable be set to a negative number, anyway?"

Because the char in unix based systems usually means signed char, which ranges from -128 to 127.
0 votes
answered Sep 12 by LiOS (4,660 points)
An alternative method to Rahul's, but I would consider your actions to your request due to the storage of values in a variable data type that is unsuitable is very dangerous, especially in C.

Below code:

#include <stdio.h>

int main()
{
    char c = -118;
    printf("%02x\n", (unsigned char)(c));
    
    return 0;
}
commented Sep 14 by Peter Minarik (7,830 points)
" the storage of values in a variable data type that is unsuitable is very dangerous, especially in C."

The signed char (which char means in unix based systems, including online GDB) can store 1 byte which ranges from -128 to 127.  I think it's perfectly suited to store -118 as well. ;)
+1 vote
answered Sep 14 by Peter Minarik (7,830 points)
edited Sep 14 by Peter Minarik

Signed number representation

In C, C++ and many modern languages, signed numbers are represented as two's complement.

So the 1 byte hex number 0x8A is the binary number 10001010. This is a signed number, negative (as it starts with a 1 bit on the most significant position -- left side). To know what number it represents, we have to reverse the two's complement format: subtract 1 bit from from the least significant position -- right side --, then invert the bits. After the subtraction we get 10001001. Inverting this we get 01110110. This equals to the decimal number 118. But we know this was a negative number (remember? most significant bit was 1), so the actual signed byte representation of 0x8A really means -118 decimal.

Okay, now that we cleared this out of the way, it will be probably easier to understand what's going on.

If you look at the specification of the printf() function, you can notice that the format parameter 'x' means unsigned hexadecimal integer. But an integer is not 1 byte, but 4 bytes. So printf() will treat -118 as an unsigned integer. The binary representation of -118 as a signed int (4 bytes) is similar to the -118 as a signed char (1 byte), except everything to the left is all 1s, that is 0xFF (for each byte). Hence the 4 byte signed representation of -118 is 0xFFFFFF8A hex. So this is what printf() puts on the standard output.

A better solution

The two other answers try to fix your input. One of them by changing the actual value (I don't really like this). The other by telling the compiler to interpret the 1 byte 0x8A as an unsigned number, instead of a signed number, so the 4 byte extension would not include all the 0xFFFFFF__ in the front. A bit better, but there's a real simple solution: read the manual. XD

printf() actually supports length modifiers for most integral numbers and their formatting. This includes the hexadecimal display x. You can apply the hh length modifier in front of x format to tell printf() that you will have a char there (1 byte) not an int (4 bytes).

So in my opinion, the proper solution is:

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

Welcome to OnlineGDB Q&A, where you can ask questions related to programming and OnlineGDB IDE and and receive answers from other members of the community.
...