检测是否发生整数截断的最佳方法是什么?
的修改
这应该导致截断信号但不是
#include <iostream>
using std::cout;
typedef signed int int32_t;
typedef unsigned int uint32_t;
typedef signed short int16_t;
typedef unsigned short uint16_t;
int32_t my32bitInt = 0xffffffff;
int32_t tmp = my32bitInt & 0xFFFF8000;
uint16_t ss = my32bitInt;
int main()
{
if (tmp != 0xFFFF8000 && tmp != 0x00000000)
{ // cannot be converted safely
cout << "truncation";
}
cout << ss << '\n';
cout << my32bitInt << '\n';
return 0;
}
修改2
template <typename U, typename T>
bool is_safe(T t)
{
return sizeof(U) <= sizeof(T) ?
(t >= static_cast<T>(std::numeric_limits<U>::min()))
&& (t <= static_cast<T>(std::numeric_limits<U>::max())) : true;
}
编辑3(基于Oli's&lt;&gt;) - 我发现了一些问题,但正在努力,将尽快更新
模板 bool is_safe(来源价值) {
if (sizeof(Result) == sizeof(Source))
{/*Same size*/
if (std::is_same<Source,Result>::value)
{
//signed to signed or unsigned to unsigned when size is same - no problem
return true;
}
else
{
//MSB mustn't be set in Source
return !(value & (1u << ((sizeof(Source) * CHAR_BIT) - 1)));
}
}
else
{//smaller to larger and larger to smaller
if (sizeof(Result) <= sizeof(Source))
{ //Larger to smaller and both equal
return ((value >= static_cast<Source>(std::numeric_limits<Result>::min()))
&& (value <= static_cast<Source>(std::numeric_limits<Result>::max())));
}
else
{ //smaller to larger
if (std::is_signed<Source>::value && !std::is_signed<Result>::value)
{
//signed to unsigned - signed must be positive
return (value >= 0);
}
else
{
return true;
}
}
}
}
答案 0 :(得分:4)
答案 1 :(得分:1)
您可以在分配后检查值是否相同。
smallInt = largeInt;
if (smallInt != largeInt)
{
// Truncation
}
或者,您可以在使用面具前检查:
if (my32bitInt & 0xFFFF0000)
{
// Can't be assigned to a 16 bit value.
}
答案 2 :(得分:0)
我不是C ++程序员,但我认为你应该做这样的事情:
#include <iostream.h>
int main()
{
float number = 0.001;
if ((int) number == number)
{
cout << "Hello world";
}
return 0;
}
希望这是一个正确的解决方案。
答案 3 :(得分:0)
如果您想在不进行转换的情况下进行检查,请以类型安全的方式检查以下内容:
template <typename U, typename T>
bool is_safe(T t)
{
return (t >= (T)std::numeric_limits<U>::min())
&& (t <= (T)std::numeric_limits<U>::max());
}
int main()
{
int32_t a = -32768;
int32_t b = +32768;
int32_t c = +32767;
int32_t d = -32769;
std::cout << is_safe<int16_t>(a) << std::endl; // 1
std::cout << is_safe<int16_t>(b) << std::endl; // 0
std::cout << is_safe<int16_t>(c) << std::endl; // 1
std::cout << is_safe<int16_t>(d) << std::endl; // 0
}
显然,如果U
的类型比T
更大,这将会中断,但我确信它可以进行调整。
答案 4 :(得分:0)
最安全的方法是在进行转换之前检查它。 These templates正是这样做的。例如:
/* unsigned -> signed, overflow */
safe_cast<short>(UINT_MAX);
/* unsigned -> unsigned, overflow */
safe_cast<unsigned char>(ULONG_MAX);
/* signed -> unsigned, overflow */
safe_cast<unsigned long>(-1);
/* signed -> signed, overflow */
safe_cast<signed char>(INT_MAX);
/* always works (no check done) */
safe_cast<long>(INT_MAX);
// giving these assertion failures results
(type)f <= (type)is_signed<To>::v_max
f <= (To)-1
f >= 0
f >= is_signed<To>::v_min && f <= is_signed<To>::v_max