标志转换在哪里发生?

时间:2013-12-01 19:30:26

标签: c++ gcc casting warnings sign

我有以下代码:

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定义?我希望有一个-运算符,它接受无符号值并返回有符号值。

4 个答案:

答案 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);

因为这可能导致有符号整数溢出 - 未定义的行为