为什么`putchar()`,`fputc()`和`putc()`的参数类型不是`char`?

有谁知道为什么putchar()fputc()putc()参数类型不是char ,但putwchar()fputwc()putwc()参数类型是wchar_t ? 另见这个和这个 。

答案是“遗产”(或“历史”)。 在C90标准之前,没有函数原型,并且所有函数的所有参数都遵循默认的促销规则,因此char自动作为int传递( short也被提升为int ,并且floatdouble ,类似于unsigned类型) )。 该标准无法破坏现有代码,因此它保留了这些函数的类型。 它在实践中几乎没有什么区别。 即使传递的值超出范围,您传递的值也将被视为字符类型。 fputc(int c, FILE *stream)的规范说:

fputc函数将c指定的字符(转换为unsigned char )写入stream指向的输出stream

默认促销规则

§6.5.2.2函数调用

¶6如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将类型为float的参数提升为double。 这些被称为默认参数促销。

¶7…函数原型声明符中的省略号表示法导致参数类型转换在最后声明的参数之后停止。 默认参数提升是在尾随参数上执行的。

整数促销在第6.3.1节中定义

¶2可以在任何可以使用intunsigned int的表达式中使用以下内容:

  • 具有整数类型( intunsigned int除外)的对象或表达式,其整数转换等级小于或等于intunsigned int的等级。
  • _Boolintsigned intunsigned int类型的位字段。

如果int可以表示原始类型的所有值(由宽度限制,对于位字段),该值将转换为int ; 否则,它将转换为unsigned int 。 这些被称为整数促销58)所有其他类型由整数促销不变。

¶3整数提升保留包括符号在内的值。 如前所述,“普通” char是否被视为已签名是实现定义的。

58)整数提升仅适用于:通常算术转换的一部分,某些参数表达式,一元+-~运算符的操作数,以及移位运算符的两个操作数,由它们各自指定小节。

整数等级在10个子弹点中的部分的¶1中定义。

我认为乔纳森的答案太简单了。 事情稍微合情合理。 我认为处理单个字符的库函数都不能使用char (仅使用int ),因为即使其中一些不使用EOF ,我们也不能在不获取类型转换警告的情况下使其类型为char

 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 

(因为人们通常将类型转换为unsigned char以确保代码的可移植性,考虑到char的签名未定义的事实。)因此唯一的选择是使其成为int