问题
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 not a very familiar character).
回答1:
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.
回答2:
-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.)
回答3:
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.
回答4:
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.
来源:https://stackoverflow.com/questions/6729488/understanding-printf-better-what-does-it-print-with-c-when-the-value-provid