2

Why fputwc(), putwc() and putwchar() take argument of type wchar_t instead of wint_t? This contradicts corresponding non-wide character functions fputc(), putc() and putchar(), which take int, not char.

Pravesh Agrawal
  • 869
  • 1
  • 11
  • 27
Igor Liferenko
  • 1,499
  • 1
  • 13
  • 28

1 Answers1

3

That is because wchar_t is required to hold an WEOF value and char is not required to hold an EOF value.

For char, the fputc(), putc() and putchar() functions need to accept values which can hold both values in the unsigned char and EOF range, where EOF can be a negative number so a int is required to hold them both.1

Whereas wchar_t itself is required to hold a WEOF character as well as the biggest locale.2 WEOF represents a value which fits inside wchar_t but doesn't overlap with any locale.3

This is made more confusing because of the the names of char and wchar_t, you shouldn't see wchar_t as a char but more as a int which size isn't dependent on the architecture but on the size of the biggest locale (and on the value of WEOF).4


1 Why putchar, toupper, tolower, etc. take a int instead of a char?

2 Quoting ISO/IEC 9899:201x 7.19.2:

WEOF which expands to a constant expression of type wint_t whose value does not correspond to any member of the extended character set. It is accepted (and returned) by several functions in this subclause to indicate end-of-file, that is, no more input from a stream. It is also used as a wide character value that does not correspond to any member of the extended character set.

3 Quoting your link:

The macro WEOF evaluates to a constant expression of type wint_t whose value is different from any member of the extended character set.

4 Quoting C++ Reference:

wchar_t Type whose range of values can represent distinct codes for all members of the largest extended character set specified among the supported locales.

In , wchar_t is a distinct fundamental type (and thus it is not defined in <cwchar> nor any other header).

In , this is a typedef of an integral type.

Community
  • 1
  • 1
tversteeg
  • 4,717
  • 10
  • 42
  • 77
  • Why in this C code gcc issues no warning? `void f(char c) {} void main(void) {f((int)65);}` Isn't there argument type mismatch? Why the following code does not issue no warning either? `...putwchar(getwchar());...` According to the definitions, argument of `putwchar` is of type **wchar_t**, but return value of `getwchar` is of type **wint_t**. Again - type mismatch. Why the warning is not produced by the compiler? – Igor Liferenko Sep 26 '16 at 01:19
  • If **wchar_t** is required to hold an `WEOF` value, why **wint_t** exists? – Igor Liferenko Sep 26 '16 at 01:22
  • What is the exact value of `WEOF`? Quoting the link http://www.gnu.org/software/libc/manual/html_node/Extended-Char-Intro.html: "ISO 10646 was designed to be a 31-bit large code space". So according to your answer `WEOF` must occupy the place of some valid iso10646 character. This is a contradiction with `EOF`: its value was chosen not to coincide with any valid 8-bit character. Please explain why `WEOF` value is taken from the range of valid iso10646 characters. – Igor Liferenko Sep 26 '16 at 01:31
  • You say that `wchar_t` must hold the value of `WEOF`. But gcc reference says that "WEOF evaluates to a constant expression of type wint_t whose value is different from any member of the extended character set". This is a contradiction. – Igor Liferenko Sep 26 '16 at 08:21
  • `wchar_t` is not a member of the extended character set, it is a type which should represent all the character sets _and_ `WEOF`. The C standard (_9899:201x_ 7.29) also mentions: "`wchar_t` and `wint_t` can be the same integer type." – tversteeg Sep 26 '16 at 08:53
  • Now I understand: ISO 10646 code space takes only 31 bits. But wchar_t (and wint_t) is 32 bits. So, we have 1 extra bit to store WEOF value. But still, having **wchar_t** *and* **wint_t** is confusing. Isn't it? Even if they both exist, shouldn't there be some consistency in using them, but not spontaneously substituting one for another? – Igor Liferenko Sep 26 '16 at 08:59
  • I think that this inconsistency should be reported to glibc developers, because if `wint_t` and `wchar_t` are the same anyway, it is better to be consistent in the function interfaces than to bring confusion. What is your opinion on whether this is worth being reported? – Igor Liferenko Sep 26 '16 at 09:06
  • The first part of the first sentence in your answer is false. – Igor Liferenko Nov 22 '16 at 05:44