检测整数截断

时间:2011-04-16 09:13:42

标签: c++

  

可能重复:
  Best way to detect integer overflow in C/C++

检测是否发生整数截断的最佳方法是什么? 的修改
这应该导致截断信号但不是

#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;
        }
    }
}

}

5 个答案:

答案 0 :(得分:4)

请参阅Boost Numeric Conversion,特别是numeric_cast

答案 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