我有以下代码:
unsigned int x, last_x;
int dx;
[...]
dx = x - last_x;
使用g ++(4.7.2)和-Wsign-conversion进行编译会产生以下结果:
warning: conversion to ‘int’ from ‘unsigned int’ may change the sign of the result [-Wsign-conversion]
使警告消失的唯一方法是更改为:
dx = static_cast<int>(x) - static_cast<int>(last_x);
或
dx = static_cast<int>(x - last_x);
这种行为有什么解释? -
运算符是否仅针对签名的int定义?我希望有一个-
运算符,它接受无符号值并返回有符号值。
答案 0 :(得分:2)
unsigned int
上的操作将导致unsigned int
s。即使减法也会产生unsigned int
。值只是包围:与有符号整数算法不同,无符号值的溢出和下溢导致良好定义的行为:算术只是模N
,其中N
是1加上可以表示的最大值无符号整数。
答案 1 :(得分:1)
编译器警告您输入的语句dx = x - last_x;
可能会导致意外的符号更改。这意味着当您执行x - last_x
时,这将是一个正数,当您将其转换为int
并将其存储在dx
时,该值可能会变为负值。
考虑将unsigned int x, last_x;
更改为int x, last_x;
。
答案 2 :(得分:0)
由于您正在处理unsigned
整数,因此在减去时必须采取预防措施以避免出现负面结果:
if (x > last_x)
{
dx = x - last_x;
}
else
{
dx = last_x - x;
}
正如其他人所说,否定结果将导致环绕。
编辑1:
如果您希望dx
成为签名结果,则应在减法之前将其他值转换为signed int
:
dx = (signed int)x - (signed int) last_x;
答案 3 :(得分:0)
警告是试图警告你事情可能出错!考虑:
unsigned int x = UINT_MAX;
unsigned int last_x = 0;
int dx = x - last_x;
显然差异是UINT_MAX
,但是这不适合int,所以你得到-1
的(可能是不合需要的)结果。
唯一一次按预期工作的是x
是循环序列的一部分(例如,时钟翻转),在这种情况下你应该使用
int dx = static_cast<int>(x - last_x);
但不
int dx = static_cast<int>(x) - static_cast<int>(last_x);
因为这可能导致有符号整数溢出 - 未定义的行为