无符号值之间的减法-意外结果
subtraction between unsigned values - unexpected result
我有两个变量(test1
和test2
),都是无符号的。我需要检查一下哪个更大。
我试图了解如果发生溢出会发生什么。
我的第一个测试是使用uint8_t(char)数据类型完成的:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main()
{
uint8_t test1 = 0;
printf("test1 = %dn", test1);
uint8_t test2 = pow(2, 8 * sizeof(test1)) - 1; //max holdable value of uint8_t
printf("test2 = %dn", test2);
uint8_t test3 = test1 - test2;
printf("test1 - test2 = %dn", test3);
if ((test1 - test2) == 0)
printf("test1 == test2n");
if ((test1 - test2) > 0)
printf("test1 > test2n");
if ((test1 - test2) < 0)
printf("test1 < test2n");
if (test3 == 0)
printf("test1 == test2n");
if (test3 > 0)
printf("test1 > test2n");
if (test3 < 0)
printf("test1 < test2n");
return 0;
}
输出:
test1 = 0
test2 = 255
test1 - test2 = 1
test1 < test2
test1 > test2
什么?生成子动作并将其保存在变量中,然后进行检查,与动态检查子动作不同吗?
我的第二个测试是使用uint32_t(long)数据类型完成的:
#include <stdio.h>
#include <stdint.h>
#include <math.h>
int main()
{
uint32_t test1 = 0;
printf("test1 = %dn", test1);
uint32_t test2 = pow(2, 8 * sizeof(test1)) - 1; //max holdable value of uint32_t
printf("test2 = %lun", test2);
uint32_t test3 = test1 - test2;
printf("test1 - test2 = %dn", test3);
if ((test1 - test2) == 0)
printf("test1 == test2n");
if ((test1 - test2) > 0)
printf("test1 > test2n");
if ((test1 - test2) < 0)
printf("test1 < test2n");
if (test3 == 0)
printf("test1 == test2n");
if (test3 > 0)
printf("test1 > test2n");
if (test3 < 0)
printf("test1 < test2n");
return 0;
}
输出:
test1 = 0
test2 = 4294967295
test1 - test2 = 1
test1 > test2
test1 > test2
什么???现在制作子动作并将其保存在一个变量中,然后检查它,是否与动态检查子动作相同?
SO我期望无符号值之间的子运算(没有显式强制转换)总是返回一个>=0的值。但是在IF内部执行子动作会导致意外的结果。
现在我很困惑。有人能向我解释一下这种行为吗?
有些晦涩难懂的类型提升规则适用。在操作数为uint8_t
的第一个示例中,对于表达式:
test1 - test2
在减法之前,两个操作数都隐式提升为int
,并且表达式本身的类型为int
。
由于类型升级,您的uint8
将升级为基于平台的int
,在当今大多数计算机中,它可能大于8位(通常为32位)。
此行:
if ((test1 - test2) < 0)
如果等同于
if ((int)((int)test1 - (int)test2) < 0) = -255 < 0
这是真的。
然而,对于这条线路,
uint8_t test3 = test1 - test2;
它相当于
uint8_t test3 = (uint8_t)((int)test1 - (int)test2); //(uint8_t)(-255) = 1!!;
所以test1 - test2 < 0
和test3 > 0
都是(欢迎来到计算机世界!)正确的!
这就解释了你的结果。
但对于uint32
,因为它的级别比原生int
"高",所以它没有"升级",一直保持为uint32
,或者换句话说,
此行:
if ((test1 - test2) > 0)
如果等同于
if ((uint32_t)((uint32_t)test1 - (uint32_t)test2) > 0) = large positive number > 0
和这条线路
uint32_t test3 = test1 - test2;
相当于
uint32_t test3 = (uint32_t)test1 - (uint32_t)test2; //also large positive number
因此您同时拥有test1 - test2 > 0
和test3 > 0
。
所以,在您的两种情况下,只有在8位机器上运行时,两者才是正确的。或者,假设将来原生int
是64位,那么这两种情况也都是正确的。。。
相关文章:
- 尝试将字符串/字符转换为整数会产生意外结果
- RapidXML - 代码创建意外结果
- 类中静态函数C++意外结果
- 指针数组中的意外结果
- 使用指针访问数组元素时出现意外结果
- 使用 sprintf 和 %g 将双精度转换为字符串的意外结果
- C++:比较运算符>和字符串文本的意外结果
- 具有意外结果的 C++ 闭包
- yaml-cpp 比较的意外结果
- 每次都出现意外结果
- 在 Qt 中解析嵌套的 JSON 时出现意外结果(数组不存在)
- 如何避免 std::abs 的意外结果?
- 使用嵌套 if 语句的意外结果
- A ^= B ^= A ^= B;C# Visual Studio 中的意外结果
- 逻辑错误,我将获得意外结果
- 在 c++ 中使用异步的意外结果
- 从函数的返回值将元素C++存储到 std::vector 中时出现意外结果
- 执行递增和递减时"cout"链接会产生意外结果
- OpenCL - 内核方法返回意外结果
- C++使用 std::get_time 解析 YYMMDD ISO 8601 日期字符串会得到意外结果