将unsigned指定为已签名,是否可以?

时间:2016-08-31 14:25:20

标签: c++ type-conversion unsigned

当我运行时:

int main() {
    unsigned a = 5;
    std::cout << -a << std::endl;
    int b = -a; 
    std::cout << b << std::endl;
    return 0;
}

我明白了:

4294967291
-5

似乎它有效,我可以接受unsigned的否定并将其分配给int,但这真的总是好吗?为什么?

当我尝试一些对我来说类似的情况时:

int c = 1;
int d = 3;
double x = c/d;
std::cout << x << std::endl;

我得到0(正如预期的那样)。

PS:也许有一个骗局,我没找到它,我能找到的最近的是this

2 个答案:

答案 0 :(得分:4)

即可。您有未定义的行为可能性。

这是一个反例,在向unsigned int指定否定的int时会产生UB:

unsigned u = (unsigned)std::numeric_limits<int>::max() - 1;
std::cout << "max int" << std::numeric_limits<int>::max() << '\n';
std::cout << "as unsigned - 1" << u << '\n';
std::cout << "negated:" << -u << '\n';
std::cout << std::boolalpha << ( std::numeric_limits<int>::max() < -u ) << '\n';
int s = -u;
std::cout << s << '\n';

在我的机器上: int的最大值是2'147'483'647,但是否定的unsigned int的值为2'147'483'650;该值大于int可表示的最大值。知道签名溢出是未定义的行为。因此,该算法对于所有可能的值都不安全。

The Standard's(2016-07-12:N4604)字样:

  

如果在评估表达式期间,结果不是   在数学上定义或不在可表示值的范围内   它的类型,行为是未定的。 [注:治疗分裂   零,使用零除数形成余数,以及所有浮点   机器之间的例外情况各不相同,有时可以通过a调整   库函数。 - 结束说明]

将来,您可以使用{} - 样式初始化来防止此类问题:

unsigned a = 5;
std::cout << -a << '\n';
int b{ -a }; // compiler detects narrowing conversions, warning/error
std::cout << b << '\n';
return 0;

请注意,即使您知道-a将是一个可由int表示的值,您的编译器仍然会发出警告。

签名溢出:

Is signed integer overflow still undefined behavior in C++?

在C和C ++中明确定义的无符号溢出:

Why is unsigned integer overflow defined behavior but signed integer overflow isn't?

隐式转化:

http://en.cppreference.com/w/cpp/language/implicit_conversion

答案 1 :(得分:0)

只要你的目标架构使用两个补码算法并将int视为32位就可以了。否则,您的第一个程序会得到不同的结果。