为什么`putwchar()`,`fputwc()`和`putwc()`的参数类型不是`wint_t`?

时间:2016-11-22 05:46:49

标签: c standards c-standard-library

引入wchar_t的ISO C90标准没有说明 关于表示的任何具体内容。它只需要 这种类型能够存储基本字符集的所有元素。

这意味着wchar_t可能属于char类型,wint_t可能属于 类型为int。此外,在某些实现中,wchar_t可以签名, 在某些 - 未签名。情况如何与putchar()不同?

为了进行比较,putchar()putc()fputc()的参数 被选为int

我认为没有一个库函数可以处理单个 字符与char一起使用(仅限int),因为即使如此 其中一些不使用EOF(如putchar()),我们无法使其类型为char, 因为如果它是char,并且我们将unsigned char版本化(char的签名未标准化),则会有类型 像

这样的转换警告
void f(char c) { ...
...
int x = 't';
f((unsigned char)x);
...

warning: conversion to ‘char’ from ‘unsigned char’ may change the sign of the result

所以唯一的选择是int,它可以包含已签名和未签名的char

虽然参数由putchar()自动转换为unsigned char,即使 它作为int或signed char传递,没有任何类型的东西在putwchar()中完成。

那么,为什么fputwc()putwc()putwchar()采用wchar_t,而不是wint_t呢?似乎是标准中的缺陷。我错过了一些明显的东西吗?

另请参阅Why islower() and friends are required to handle EOF?Why argument type of putchar(), fputc() and putc() is not char?以及Inconsistency in definitions of fputwc(), putwc() and putwchar() in glibc

更新

来自glibc参考的一些引用

  

如果wchar_t被定义为char,则由于参数提升,必须将wint_t类型定义为int

  

wchar_t定义为char

是合理的

事实上,这些功能在1992年3月31日的“ISO工作文件SC22 / WG14 / N204”中具有正确的界面(这是在发布“ISO / IEC 9899:1990 / Amendment 1:1995”之前的最终草案),但是它们在“ISO / IEC 9899:1990 / Amendment 1:1995”中有所改变。见http://www.unix.org/version2/whatsnew/login_mse.html

1 个答案:

答案 0 :(得分:2)

这是一个有趣的问题,但不幸的是,我认为答案仅仅是出于历史原因的 。这个答案的其余部分只是我的观点,我没有参考。

自K& RC的第一个版本以来fputc系列已存在,其中函数的原型甚至不存在:您应该知道函数接受的参数类型,并且没有隐式转换可以发生在函数调用中。当fgetc系列返回一个int时,决定对称fputc一个将int作为参数以允许以下构造:

fputc(fgetc(fd1), fd2);

如果fputc使用了字符,则应该写入(K& R C):fputc((char) fgetc(fd1), fd2);

但是现在,只有恐龙可以从K& R中记住,并且在函数调用中会发生隐式转换。因此,当将宽字符集函数添加到标准库时,决定仅传递用于避免双重转换的部分wchar_t - > wint_t - > wchar_t因为只使用了wchar_t。它在fputs定义(强调我的)中是明确的:

  

int fputc(int c, FILE *stream);
  描述:fputc函数写入由c指定的字符(转换为无符号   char )到stream ...

指向的输出流

所以它不是很连贯,但我想没有人真的认为有必要改变旧fputc家庭功能的定义......