C / C++中无符号整数的减法和比较是否定义良好?
Is subtraction and comparison with unsigned integers in C / C++ well defined?
作为对"无符号整数减法是否定义了行为?"问题的扩展,我对以下行为感到困惑。
在下面的代码中,请注意,A = 50
和B = 100
存储为无符号 16 位整数,减法A - B = -50 = 65486 (mod 2^16 - 1)
。如果我将减法的结果存储在D
(一个无符号的 16 位整数)中,然后评估D > 4000
我得到true
,因为65486 > 4000.
这是有道理的。
如果我放弃存储A - B
并直接评估A - B > 4000
,我会得到错误。这似乎不一致。这是预期的结果吗?为什么?这始终是正确的行为,还是我处于"未定义行为"的状态。
#include <stdio.h>
#include <stdint.h>
int main() {
uint16_t A = 50;
uint16_t B = 100;
uint16_t D = A - B; // D = 65486
printf("D = %un", D);
int R = D > 4000; // R = 1 (true)
printf("R = %dn", R);
int S = A - B > 4000; // S = 0 (false)
printf("S = %dn", S);
return 0;
}
顺便说一句,这种行为似乎与这个问题的代码中的行为相矛盾,这进一步让我感到困惑。如果我将uint16_t
更改为上面的uint32_t
,则得到
D = 4294967246
R = 1
S = 1
这对我来说似乎是正确的。
更新:似乎最好的详细答案是uint16_t
被提升为int
(int
在我的系统上是 32 位),因此A - B > 4000
是用有符号算术完成的。而当我切换到uint32_t
时,没有执行任何提升(已经是 32 位宽),因此A - B > 4000
是用无符号算术完成的。这可以解释它。
附言我知道人们想第一个回答,但仅仅说"整数提升"不是一个有用的答案。
如果我放弃存储 A - B 并直接评估 A - B> 4000,我会得到错误。这似乎不一致。
是的,粗略地看一下。
但是,当计算表达式A-B
时,在执行减法之前,两者都会提升为int
。因此,A - B > 5000
计算结果为 false。
您可以在 http://en.cppreference.com/w/c/language/conversion 阅读"常用算术转换"。
但是当我切换到unit32_t
时呢:
当两个操作数都是类型unit32_t
时,在sizeof(int)
为 4 而不是int
的平台上,结果也是类型unit32_t
的。
- std::less是否应该允许在编译时比较不相关的指针?
- 对于BTreeMap和其他依赖于Ord的东西,是否有等效于C++比较器对象?
- 用户定义的结构是否有默认C++比较器?
- gcc 是否在 2 条短裤的过度对齐结构的比较中错过了优化机会?
- 这种比较是否不一致(或者存在其他问题)?
- 通过默认复制构造函数比较 C++ 字符串是否会影响性能,原因为何?
- 是否可以在C++中使用三元运算符在 if 语句中选择比较运算符?
- 我如何比较这些不同的输出,看看它们是否相等
- C++中是否有任何常量可以用作比较中的最小值/最大值
- 函数指针的比较是否合法
- 是否有任何统一的方法可以在 c++ 中创建自定义比较器?
- C++是否保证标准容器比较中操作数的顺序?
- C++中的结构是否按顺序分配内存?每次都以某种方式获得指针比较的正确答案
- C 是否具有对两个STD :: sets,vectors等进行三角比较的标准方法
- 比较BGR图像是否完全相同
- qsort C++是否曾经将元素与自身进行比较?
- 是否可以将两个任意函数与 C++17 中的 std::any 进行比较
- 是否可以比较两个函子的相等性
- 将无符号的 int 与 std::string::size_type 进行比较是否安全
- 三向比较运算符是否始终有效