【发布时间】:2016-02-17 07:15:14
【问题描述】:
为什么在 C++11 中 unsigned short * unsigned short 会转换为 int?
int 太小,无法处理这行代码所示的最大值。
cout << USHRT_MAX * USHRT_MAX << endl;
MinGW 4.9.2 上的溢出
-131071
因为 (source)
USHRT_MAX = 65535 (2^16-1) 或更大*
INT_MAX = 32767 (2^15-1) 或更大*
和(2^16-1)*(2^16-1) = ~2^32。
我应该预料到这个解决方案会出现什么问题吗?
unsigned u = static_cast<unsigned>(t*t);
这个程序
unsigned short t;
cout<<typeid(t).name()<<endl;
cout<<typeid(t*t).name()<<endl;
给出输出
t
i
开
gcc version 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
gcc version 4.8.2 (GCC)
MinGW 4.9.2
两者都有
g++ p.cpp
g++ -std=c++11 p.cpp
这证明t*t 在这些编译器上被转换为int。
有用的资源:
Signed to unsigned conversion in C - is it always safe?
Signed & unsigned integer multiplication
https://bytes.com/topic/c-sharp/answers/223883-multiplication-types-smaller-than-int-yields-int
http://www.cplusplus.com/reference/climits
http://en.cppreference.com/w/cpp/language/types
编辑:我已经在下图中展示了这个问题。
【问题讨论】:
-
如果
int在您的平台上是 16 位,那么您得到的结果不是int。请注意您链接到的表中值的免责声明:“实际值取决于特定的系统和库实现,但应反映目标平台中这些类型的限制。” -
您确定
USHRT_MAX是unsigned short类型吗?在我的环境中(Lubuntu 下的 GCC 4.8 64 位),USHRT_MAX实际上是int类型(定义为(32767 * 2 + 1))。难怪USHRT_MAX*USHRT_MAX会溢出。 -
有一个错字,我更正了。有什么改变吗?
-
USHRT_MAX是0xFFFF和0xFFFF * 0xFFFF = 0xFFFE0001(没有溢出)这等于4294836225或-131071所以这只是到int的最终转换,它把它扔掉了。 -
@BarmakShemirani
INT_MAX是0x7FFFFFFF,所以这实际上是溢出。
标签: c++ c++11 types type-conversion integer-promotion