为什么 char 既没有符号也没有符号,但 wchar_t 是?

Why is char neither signed or unsigned, but wchar_t is?

以下 C++ 程序编译无误:

void f(char){}
void f(signed char){}
void f(unsigned char){}
int main(){}  

同一程序的 wchar_t 版本没有:

void f(wchar_t){}
void f(signed wchar_t){}
void f(unsigned wchar_t){}
int main(){}

错误:'void f(wchar_t)'的重新定义
void f(有符号 wchar_t){}

好像wchar_tunsigned
为什么重载会出现不一致?

char都是不同的类型,可以重载

[basic.fundamental] / 1

[...] Plain char, signed char, and unsigned char are three distinct types, collectively called narrow character types. [...]

wchar_t也是一个distinct类型,但是不能用signed或者unsigned来限定,只能和标准整数类型一起使用。

[dcl.type] / 2

As a general rule, at most one type-specifier is allowed in the complete decl-specifier-seq of a declaration or in a type-specifier-seq or trailing-type-specifier-seq. The only exceptions to this rule are the following:

[...]

signed or unsigned can be combined with char, long, short, or int.

[dcl.type.简单] / 2

[...] Table 9 summarizes the valid combinations of simple-type-specifiers and the types they specify.

wchar_t 的符号是实现定义的:

[basic.fundamental] / 5

[...] Type wchar_t shall have the same size, signedness, and alignment requirements (3.11) as one of the other integral types, called its underlying type.

char 是不同于 signed charunsigned char 的类型。 wchar_t 是另一种不同的类型(用于类型标识目的),但它具有与其他整数类型完全相同的属性(大小、符号和对齐)。

来自 ISO 14882:2003、3.9.1:

Plain char, signed char, and unsigned char are three distinct types.

(...)

Type wchar_t is a distinct type whose values can represent distinct codes for all members of the largest extended character set specified among the supported locales (22.1.1). Type wchar_t shall have the same size, signedness, and alignment requirements (3.9) as one of the other integral types, called its underlying type.

没有signed wchar_tunsigned wchar_t这样的东西。文档中没有任何地方提到它。

char 是基本类型。 wchar_t 首先作为库解决方案(在 C 中)发展,然后成为内置类型 具有基础类型 ,对应于早期用于 [=12 的类型=]它:

C++11 $3.9.1/5

Type wchar_t shall have the same size, signedness, and alignment requirements (3.11) as one of the other integral types, called its underlying type.

这解释了为什么您不能更改 wchar_t 的符号,但它没有解释为什么 char 类型具有未指定的符号。


此外,大多数编译器默认选择带符号的 char 由于多种原因是不切实际的。一个原因是负值很烦人,通常必须转换为无符号才能比较它们。另一个原因是 C 字符分类函数需要非负值(传递 EOF 时除外)。第三个原因是在旧的大小和符号或补码机器上有一个不可用的值。

Stroustrup 的“C++ 的设计与演化”中可能对此有一些解释,但我对此表示怀疑。

这听起来像是冻结的历史,对于当时的技术来说,这在某一时刻具有某种意义。