c++ - 对无符号变量进行算术运算会产生有符号值,这是标准行为吗?
问题描述
减去两个无符号变量,我期望得到无符号结果。我确实意识到会发生溢出,但没关系,我实际上指望它。当结果需要在另一个操作中使用时,似乎情况并非如此。这是标准行为还是未定义行为?
uint8_t n1 = 255;
uint8_t z = 0;
uint8_t n = 1;
printf("n1 is %" PRIu8 "\n", n1);
printf("z - n is %" PRIu8 "\n", z - n);
printf("n1 < z: %s\n", n1 < z ? "yes" : "no");
printf("z - n < z: %s\n", z - n < z ? "yes" : "no");
printf("(uint8_t)(z - n) < (uint8_t)z: %s\n", (uint8_t)(z - n) < (uint8_t)z ? "yes" : "no");
输出:
n1 is 255
z - n is 255
n1 < z: no
z - n < z: yes
(uint8_t)(z - n) < (uint8_t)z: no
解决方案
当变量的类型为 时uint8_t
,它们都被提升为(有符号)int
,然后在提升的值之间发生减法,产生一个(有符号)int
值。这是强制性的行为。
在 C11 中,§6.3.1.8 通常的算术转换说:
许多期望算术类型的操作数的运算符会以类似的方式导致转换和产生结果类型。目的是确定操作数和结果的通用实数类型。对于指定的操作数,每个操作数都在不改变类型域的情况下转换为对应的实数类型是公共实数类型的类型。除非另有明确说明,否则公共实数类型也是结果的对应实数类型,如果操作数相同,则其类型域为操作数的类型域,否则为复数。这种模式称为通常的算术转换:
- 首先,如果任一操作数的对应实类型为
long double
,则将另一个操作数转换为对应实类型为 的类型,而不改变类型域long double
。- 否则,如果任一操作数的对应实类型为
double
,则将另一个操作数转换为对应实类型为 的类型,而不改变类型域double
。- 否则,如果任一操作数的对应实类型为
float
,则将另一个操作数转换为对应实类型为 的类型,而不改变类型域float
。62)- 否则,对两个操作数都执行整数提升。然后将以下规则应用于提升的操作数:
- 如果两个操作数具有相同的类型,则不需要进一步转换。
- 否则,如果两个操作数都具有有符号整数类型或都具有无符号整数类型,则具有较小整数转换等级的类型的操作数将转换为具有较高等级的操作数的类型。
- 否则,如果无符号整数类型的操作数的等级大于或等于另一个操作数类型的等级,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。
- 否则,如果有符号整数类型的操作数的类型可以表示无符号整数类型的操作数的所有值,则将无符号整数类型的操作数转换为有符号整数类型的操作数的类型。
- 否则,两个操作数都转换为与带符号整数类型的操作数类型对应的无符号整数类型。
有关“整数提升”的更多信息,请参阅§6.3.1 算术操作数和§6.3.1.1 布尔值、字符和整数。
以下可以用在表达式中,只要可以使用
int
orunsigned int
:
- 具有整数类型(除
int
or之外unsigned int
)的对象或表达式,其整数转换等级小于或等于int
and的等级unsigned int
。_Bool
,int
,signed int
或类型的位域unsigned int
。如果 an
int
可以表示原始类型的所有值(受宽度限制,对于位域),则该值将转换为int
; 否则,将其转换为unsigned int
. 这些被称为整数促销。58)整数提升不会改变所有其他类型。
术语“等级”在该部分中定义;它很复杂,但基本上,long
排名高于int
,并且int
排名高于char
。
毫无疑问,C++ 中的规则略有不同,但最终结果基本相同。
推荐阅读
- jquery - 在 AMP html 中使用 JQuery 时出现错误如何解决?
- mysql - Mysql NOT IS NULL 行为
- ios - 当设备处于 IOS 13 的暗模式时如何将您的应用程序限制为亮模式
- javascript - React-Native 中的树视图
- python-3.x - 尝试从单个函数获取两个列表时出现 ValueError
- python - 如何自动分页而不是在烧瓶中使用限制和偏移量
- .net-core - 如何将 Google API 范围添加到 IdentityServer4
- node.js - Mongo 查询字段并且不返回重复项
- r - 如何在 R 中生成带有条形堆栈(不同颜色)的 gap.barplot?
- java - 对从 csv 文件导入的数组列表进行小计