开发者

Understanding printf better - What does it print with "%c" when the value provided is negative?

In Kernighan & Ritchie, it says that "all printable characters are positive when though char datatype being signed or unsigned is machine-dependent."

Can somebody explain to me the meaning of this line ? My system has signed chars but even with a negative value say of -90, printf does print a character (even though its开发者_JAVA百科 not a very familiar character).


ASCII character set defines codepoints from 0x00 to 0x7F. It doesn't matter if they are represented with unsigned or signed byte values since this range is common for both.

Printable characters are between 0x20 and 0x7E, which are all part of the ASCII. The term printable character does not define every possible character in the world that is printable. Rather it is defined inside the realm of ASCII.

Byte values from 0x80 to 0xFF are not defined in ASCII and different systems assign different characters to values in this range resulting in many different types of codepages which are identical in their ASCII range but differ in this range. This is also the range where values for signed and unsigned bytes differ.

The implementation of printf looks for a single byte value when it encounters a %c key in its input. This byte value may be signed or unsigned with respect to your point of view as the caller of printf function but printf does not know this. It just passes these 8bits to the output stream it's connected to and that stream emits characters within 0x00 and 0xff.

The concept of sign has no meaning inside the output pipeline where characters are emitted. Thus, whether you send a 255 or a -1, the character mapped to 0xFF in the specific codepage is emitted.


-90 as a signed char is being re-interpreted as an unsigned char, in which case it's value is 166. (Both -90 and 166 are 0xA6 in hex.)


That's right. All binary numbers are positive. Whether you treat it as negative or not is your own interpretation. Using the common two's compliment.

The 8-bit number: 10100110 is positive 166, which is greater that 128 (The maximum positive signed 8 bit number).

Using signed arithmatic the number 166 is -90.

You are seeing the character whose ascii value is 166.


Using this as an example:

signed char x = -90;
printf("%c", x);

The integer promotion rules convert x into an int before passing it as an argument to printf. (Note, none of the other answers mention this detail, and several imply the argument to printf is still a signed char).

Section 7.21.6.1.6 of the standard (I'm using the C11 standard) says of the %c flag character:

If no l length modifier is present, the int argument is converted to an unsigned char, and the resulting character is written.

So the integer -90 gets converted into an unsigned char. That means (6.3.1.3.2):

...the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

If an unsigned char on your system takes the values 0 to 255 (which it almost certainly does), then the result will be -90 + 256 = 166. (Note: other answers refer to the "lowest byte" or "hex representation" assuming two's complement representation. Although this is overwhelmingly common, the C standard does not guarantee it).

The character 166 is then written to stdout, and interpreted by your terminal.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜