把负的或无符号的赋值给有符号的,可以吗
Assign negative of unsigned to a signed, is it OK?
当我运行这个时:
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:也许有一个骗局,我没有找到它,我能找到的最接近的是这个
不。你有未定义行为的可能性。
这里是一个反例,当将否定的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) word:
如果在表达式求值期间,结果不是在数学上定义的或不在可表示值范围内的它的类型、行为是未定义的。[注:除法处理按零,使用零除数形成余数,以及所有浮点数异常因机器而异,有时可通过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
表示的值,您的编译器仍然警告您。
On signed overflow:
有符号整数溢出在c++中仍然未定义行为吗?
C和c++中定义良好的无符号溢出:
为什么无符号整数溢出是定义行为,而有符号整数溢出是n't?
关于隐式转换:
http://en.cppreference.com/w/cpp/language/implicit_conversion只要您的目标架构使用2的互补算法并将int
视为32位,就可以了。否则,第一个程序将得到不同的结果。
相关文章:
- 为什么 std::(i)ostream 将有符号/无符号字符视为文本而不是整数
- 警告 C4018:">=":VSC++ 2010 中的有符号/无符号不匹配
- 有符号/无符号不匹配,并且函数在转换为函数时不带2个参数
- 符号"重新声明(有符号/无符号,精度)与
- 有符号/无符号特征编程
- 有符号/无符号 int 不匹配
- 断言(true)警告有符号/无符号不匹配
- 有符号/无符号比较警告是什么意思
- 数组索引的类型:有符号/无符号整数先锋
- 没有兼容的方法来转换相同大小的有符号/无符号
- 溢出的有符号/无符号赋值及其结果
- C++隐式转换(有符号 + 无符号)
- 增强size_type的有符号/无符号比较和multi_array的索引
- 警告 C4018:'>':有符号/无符号不匹配
- c++自动重写有符号/无符号
- C++警告 C4018:"<":有符号/无符号不匹配
- 错误:comp. bet.有符号/无符号整数表达式
- gcc和有符号/无符号比较的奇怪警告行为
- Visual Studio 2013有符号/无符号整数数学行为不同时,求值表达式作为函数参数,编译器切换
- 整数提升,有符号/无符号,和打印