为啥 char 既不是有符号也不是无符号,而 wchar_t 是?
Posted
技术标签:
【中文标题】为啥 char 既不是有符号也不是无符号,而 wchar_t 是?【英文标题】:Why is char neither signed or unsigned, but wchar_t is?为什么 char 既不是有符号也不是无符号,而 wchar_t 是? 【发布时间】:2015-12-27 16:07:41 【问题描述】:以下 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(signed wchar_t)
看来wchar_t
是unsigned
。
为什么过载时会出现不一致?
【问题讨论】:
这在我看来不像合法的 C。是 C++ 吗? @ArlieStephens 是的,最好删除 C 标签。无需任何标头的 C++。wchar_t
允许根据 [basic.fundamental] 签名或未签名。
@chris 我明白了。所以 wchar_t 是两者之一,而 char 两者都不是。
wchar_t
与char
的不同之处在于char
可能是有符号类型或无符号类型,但仍是不等同于signed char
和unsigned char
的类型,与@ 不同987654332@ 可能是有符号或无符号类型,无法指定单独的 signed wchar_t
或 unsigned wchar_t
类型。
【参考方案1】:
char
s 都是不同的类型,可以重载
[basic.fundamental] / 1
[...] 普通
char
、signed char
和unsigned char
是三种不同的类型, 统称为窄字符类型。 [...]
wchar_t
也是一个distinct类型,但不能用signed
或unsigned
限定,只能和标准整数类型一起使用。
[dcl.type] / 2
作为一般规则,最多允许一个 type-specifier 声明的完整 decl-specifier-seq 或 type-specifier-seq 或 trailing-type-specifier-seq。唯一的例外 这条规则如下:
[...]
signed
或unsigned
可以与char
、long
、short
或int
组合使用。
[dcl.type.simple] / 2
[...] 表 9 总结了 simple-type-specifiers 及其指定类型的有效组合。
wchar_t
的签名由实现定义:
[basic.fundamental] / 5
[...] 类型
wchar_t
应具有相同的大小、符号和对齐方式 要求(3.11)作为其他整数类型之一,称为其 底层类型。
【讨论】:
我想知道为什么我的编译器让我摆脱“unsigned wchar_t”,如果它不是一个有效的限定符。我当然不能做像“unsigned bool”这样的事情...... @TrevorHickey 提交错误报告:)【参考方案2】:char
是与signed char
和unsigned char
不同的类型。 wchar_t
是另一种不同的类型(用于类型标识目的),但它具有与其他整数类型完全相同的属性(大小、符号和对齐方式)。
来自 ISO 14882:2003, 3.9.1:
Plain
char
、signed char
和unsigned char
是三种不同的类型。(...)
Type
wchar_t
是一个 distinct 类型,其值可以表示 distinct 指定的最大扩展字符集的所有成员的代码 在受支持的语言环境(22.1.1)中。类型wchar_t
应具有相同的 尺寸、签名和对齐要求 (3.9) 作为其他要求之一 整数类型,称为其底层类型。
没有signed wchar_t
或unsigned wchar_t
这样的东西。文档中没有提到它。
【讨论】:
【参考方案3】:char
是基本类型。 wchar_t
首先演变为库解决方案(在 C 中),然后成为内置类型具有底层类型,对应于之前用于 typedef
它的类型:
” 类型
wchar_t
应具有相同的 大小、符号和对齐要求 (3.11) 作为其他整数类型之一,称为其基础 输入。
这解释了为什么您不能更改 wchar_t
的签名,但它没有解释为什么存在未指定签名的 char
类型。
此外,大多数编译器默认选择带符号的char
是不切实际的,原因有几个。一个原因是负值很烦人,通常必须转换为无符号才能比较它们。另一个原因是 C 字符分类函数需要非负值(传递 EOF
时除外)。第三个原因是,在旧的幅度和符号或反码机器上,有一个不可用的值。
Stroustrup 的“C++ 的设计和演变”中可能对此有一些解释,但我对此表示怀疑。
这听起来像冻结的历史,对于当时的技术来说,这在某种程度上是有意义的。
【讨论】:
以上是关于为啥 char 既不是有符号也不是无符号,而 wchar_t 是?的主要内容,如果未能解决你的问题,请参考以下文章