Does anybody know Why argument type of putchar()
, fputc()
and putc()
is not char
, but argument type of putwchar()
, fputwc()
and putwc()
is wchar_t
? See also this and this.
问题:
回答1:
The answer is 'legacy' (or 'history'). Before the C90 standard, there were no function prototypes and all arguments to all functions were subject to default promotion rules, so a char
was automatically passed as an int
(short
was promoted to int
too, and float
to double
, and similarly for unsigned types). The standard couldn't afford to break existing code, so it kept that type for these functions. It makes very little difference in practice. The value you pass will be treated as a character type even if you pass a value that's out of range. The specification of fputc(int c, FILE *stream)
says:
The
fputc
function writes the character specified byc
(converted to anunsigned char
) to the output stream pointed to bystream
…
Default promotion rules
§6.5.2.2 Function calls
¶6 If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. …
¶7 … The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument promotions are performed on trailing arguments.
Integer promotions are defined in §6.3.1
¶2 The following may be used in an expression wherever an
int
orunsigned int
may be used:
- An object or expression with an integer type (other than
int
orunsigned int
) whose integer conversion rank is less than or equal to the rank ofint
andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned int
.If an
int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to anint
; otherwise, it is converted to anunsigned int
. These are called the integer promotions.58) All other types are unchanged by the integer promotions.¶3 The integer promotions preserve value including sign. As discussed earlier, whether a 'plain'
char
is treated as signed is implementation-defined.58) The integer promotions are applied only: as part of the usual arithmetic conversions, to certain argument expressions, to the operands of the unary
+
,-
, and~
operators, and to both operands of the shift operators, as specified by their respective subclauses.
The integer ranks are defined in ¶1 of the section in 10 bullet points.
回答2:
I think that Jonathan's answer is too simple. Things are slightly more rational. I think that none of the library functions which handle single
characters work with char
(only with int
), because even though some of them do not use EOF
, we cannot make its type char
without
getting type conversion warnings like
void f(char c) { ...
...
char x = 't';
f((unsigned char)x);
...
warning: conversion to ‘char’ from ‘unsigned char’ may change the sign of the result
(because people usually typecast to unsigned char to ensure portability of the code, considering the fact that the signedness of char
is undefined.)
So the only option was to make it int
.