为什么对无符号字符进行算术运算会将它们提升为有符号整数
Why do arithmetic operations on unsigned chars promote them to signed integers?
许多类似问题的答案都指出,这是标准造成的。但是,我无法理解标准制定者做出这一决定的原因。
根据我的理解,unsigned char
不会以2的补码形式存储值。因此,我不认为对两个unsigned chars
进行XOR会产生意外行为。因此,将它们升级到int
似乎只是浪费空间(在大多数情况下)和CPU周期。
此外,为什么是int
?如果一个变量被声明为unsigned
,那么无符号性对程序员来说显然很重要,因此在我看来,升级为unsigned int
仍然比int
更有意义。
[EDIT#1]如评论中所述,如果int
不能充分容纳unsigned char
中的值,则将升级为unsigned int
。
[编辑#2]为了澄清这个问题,如果它是关于在int
上运行比在char
上运行的性能优势,那么为什么它在标准中?这本可以作为一个建议给编译器设计者,以便更好地进行优化。现在,如果有人设计了一个不这样做的编译器,这将使他们的编译器成为一个不完全遵守C/C++标准的编译器,尽管假设这个编译器确实支持该语言的所有其他必需功能。简言之,我不知道为什么我不能直接在unsigned chars
上操作,因此要求将它们升级到ints
似乎没有必要。你能给我举个例子证明这是错误的吗?
您可以在线找到本文档:《国际标准原理-程序设计语言-C》(2003年5月10日修订版)。
第6.3章(第44-45页)是关于的转换
在K&R和C89的开发,在整数提升规则的演变过程中,实现之间出现了严重的分歧。实现分为两大阵营,其特征可以是无符号保留和
值保留当整数提升扩大时,这些方法之间的差异集中在
unsigned char
和unsigned short
的处理上,但该决定也对常数的类型产生了影响(见§6.4.4.1)无符号保留方法要求将两个较小的无符号类型提升为
unsigned int
。这是一个简单的规则,并产生一个独立于执行环境的类型。值保留方法要求将那些类型提升为
signed int
,如果该类型可以正确地表示原始类型的所有值,则要求将这些类型提升为unsigned int
。因此,如果执行环境将
short
表示为小于int
的东西,则unsigned short
变为int
;否则变为CCD_ 24。在绝大多数情况下,这两种方案都给出了相同的答案,在使用二的补码算法和对有符号溢出的安静环绕的实现中,也就是在大多数当前实现中,这两个方案在更多情况下都给出了同样的有效结果。在这样的实现中,只有当这两个条件都成立时,两者之间才会出现差异:
涉及
unsigned char
或unsigned short
的表达式会产生一个int
范围的结果,其中设置了符号位,也就是说,对这种类型进行一元运算,或者进行二进制运算,其中另一个操作数是int
或"较窄"类型。上一个表达式的结果用于其签名性显著的上下文中:
•
sizeof(int) < sizeof(long)
,并且必须将其扩展为长类型或•在将右移定义为算术或的实现中,它是右移运算符的左操作数
•它是/、%、<、<=,>,或>=。
在这种情况下,会产生真正的解释歧义。结果必须被称为有疑问的签名,因为可以为签名或无签名的解释设置案例。每当
unsigned int
通过运算符与signed int
对抗,并且signed int
具有负值时,就会出现完全相同的模糊性。在解决这场对抗的模糊性方面,这两种方案都没有起到更好或更坏的作用。突然间,负signed int
变成了非常大的unsigned int
,这可能令人惊讶,也可能正是知识渊博的程序员所希望的。当然,所有这些歧义都可以通过明智地使用强制类型转换来避免。探索这个问题的一个重要结果是理解高质量的编译器可能会很好地寻找这种有问题的代码并提供(可选的)诊断,而认真的导师可能会很容易地警告程序员隐式类型转换的问题。
无符号保留规则极大地增加了
unsigned int
与signed int
对抗以产生有疑问的有符号结果的情况的数量,而值保留规则最小化了这种对抗。因此,对于新手或粗心的程序员来说,保值规则被认为是更安全的。经过多次讨论,C89委员会决定支持值保留规则,尽管UNIXC编译器已经朝着无符号保留的方向发展。C89 的安静变化
一个依赖于无符号保留算术转换的程序会有不同的行为,可能不会引起抱怨。这被认为是C89委员会对目前广泛使用的做法所做的最严重的语义改变。
作为参考,您可以在Lundin的回答中找到有关更新到C11的转换的更多详细信息。
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 检查TCHAR数组输入是否为带符号整数C++
- 如何打印boost多精度128位无符号整数
- C++模板函数,用于比较任何无符号整数和有符号整数
- 在数字之间插入 + 或 - 符号以使其等于整数
- 为什么:不同符号的整数比较只是偶尔发生?
- 将超出范围的整数分配给有符号字符类型
- 为什么乘以常量有符号整数分数没有优化?
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 在线程中读取无符号整数时,c++ 位是否以原子方式切换?
- FlatBuffers/Protobuf 中是否有支持任意 24 位有符号整数定义的可移植二进制序列化架构?
- C++11 标准是否保证零值有符号整数的一元减号为零?
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- Constexpr 可变参数模板,用于对无符号整数进行重新排序
- AVX2 整数乘以有符号 8 位元素,产生有符号 16 位结果?
- 为什么 Clang 和 GCC 中两个无符号整数之和的结果类型不同
- 使用192/256位整数求和无符号64位整数向量的点积的最快方法
- 为什么对无符号字符进行算术运算会将它们提升为有符号整数
- 从 std::string 转换为 const 无符号整数
- 矢量浮点到整数/符号转换