将无符号的负数分配给有符号的,可以吗?
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:也许有一个骗子,但我没有找到,我能找到的最接近的是
只要您的目标体系结构使用二进制补码算法并将 int
视为 32 位,就可以了。否则你的第一个程序会得到不同的结果。
否。您有 未定义的行为 种可能性。
这是一个反例,在将取反的 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
可以表示的最大值。知道有符号溢出是未定义的行为。因此,该算法对其所有可能值都不安全。
标准的(2016-07-12:N4604)词:
If during the evaluation of an expression, the result is not
mathematically defined or not in the range of representable values for
its type, the behavior is undefined. [ Note: Treatment of division by
zero, forming a remainder using a zero divisor, and all floating point
exceptions vary among machines, and is sometimes adjustable by a
library function. — end note ]
将来,您可以使用 {}
式初始化来防止此类问题:
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
当我运行这个:
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:也许有一个骗子,但我没有找到,我能找到的最接近的是
只要您的目标体系结构使用二进制补码算法并将 int
视为 32 位,就可以了。否则你的第一个程序会得到不同的结果。
否。您有 未定义的行为 种可能性。
这是一个反例,在将取反的 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
可以表示的最大值。知道有符号溢出是未定义的行为。因此,该算法对其所有可能值都不安全。
标准的(2016-07-12:N4604)词:
If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined. [ Note: Treatment of division by zero, forming a remainder using a zero divisor, and all floating point exceptions vary among machines, and is sometimes adjustable by a library function. — end note ]
将来,您可以使用 {}
式初始化来防止此类问题:
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