修复“有符号和无符号整数之间的比较”警告的首选方法是什么?

时间:2010-12-20 04:05:15

标签: c integer unsigned signed

什么是安全地修复“有符号和无符号整数之间的比较”警告的首选方法?在我的例子中,我必须将一些uint_32变量与#define常量进行比较。

真的很简单:

#define MAX(A,B) ({ __typeof__(A) __a = (A); __typeof__(B) __b = (B); __a < __b ? __b : __a; })
#define c (10)
unsigned int d = 11;
if(MAX(c,d)>10){
  //...
}

但我确实很多这样的情况 - 你有什么建议来解决这个问题?

4 个答案:

答案 0 :(得分:3)

在这种情况下,您也可以将常量更改为无符号:

#define c 10U

或者使用强制转换,以便宏中的typeof创建unsigned变量:

if (MAX((unsigned)c, d) > 10) {

答案 1 :(得分:1)

我不知道是否完全正确,但我的逻辑说明了这一点: 如果int(签名)是&lt; 0,该值小于无符号值。 否则,您可以将其强制转换为unsigned int

那么这个:

#define INT_MAX_UINT(value1,value2) (value1<0?value2:(((uint)value1)>value2?value1:value2))

这是最好的主意,但是你不能把它变成“通用”,我的意思是如果你想要反转params命令你必须构建一个UINT_MAX_INT

如果您使用的是Visual Studio而您根本不想听到警告(因为您确定它不会出现任何问题): http://msdn.microsoft.com/en-us/library/2c8f766e%28v=vs.80%29.aspx

祝你好运

答案 2 :(得分:0)

我的简单建议是使用你对signed和unsigned int类型的了解。

也许你可以试试:

#include <limits.h>

unsigned int max(int six, unsigned int uix) {
   if (uix > INT_MAX || six < 0) { return uix; }
   return ((unsigned int) six >= uix) ? (unsigned int) six : uix;
}

注意“类型传染”(我想不出一个更好的词来描述它,因为效果是隐含的)

你甚至可以内联这个功能。

答案 3 :(得分:0)

我使用“保值”的C ++促销活动。问题是如何查找操作数需要被提升。签名的unsigned之间的比较等同于签名号为正数后的无符号比较。 如果两个数字具有相同的大小,我将其转换为无符号的其他,我会投射到最大的数字。 不太平等的下一个模板实现对我来说很好。

/*
 * Signed unsigned safe less equal function implementation
 * 
 * a <=b
 * int uint --> (a <= 0) || ( b >= (B)a  && a <= (A)b )
 * uint int --> (b >= 0) && ( a <= (A)b  && b >= (B)a )
 *
 * all comparations are done using positive numbers
 * If integral promotion is used then one condition can be remove
 *
 *  a <= b
 * int  uint --> (a <=0) ||  [ (uint)a <= b | a <= (int)b ]
 * uint int  --> (b >=0) ||  [ (uint)a <= b | a <= (int)b ]
 *
 * The question is. cast to B or to A?
 *
 *  size A = size B
 *  uint <= int  A
 *  int  <= uint B
 *
 *  size A > size B
 *  uint <= int  A
 *  int  <= uint A
 *
 *  size A < size B
 *  uint <= int B
 *  int <= uint B
 */
namespace Range
{
    /*
     * if sizeof A > sizeof B then casting to A
     * if sizeof A < sizeof B then casting to B
     * if sizeof A == sizeof A then
     *  if A is signed cast to B else cast to A
     *
     * true means static cast to A
     */
    template<size_t a,size_t b,bool intA>
    struct _le_cast_to_a_
    {
        constexpr static const bool value = (a > b) ? true : (a < b) ? false : intA ? false : true;
    };

    // Casting to A default implementation
    template<bool cast_to_a = true>
    struct _less_equal
    {
        template <class A,class B>
        static inline bool le(A a,B b)
        {
            return (a <= static_cast<A>(b));
        }
    };
    // Casting to b specialization
    template<>
    struct _less_equal<false>
    {
        template <class A,class B>
        static inline bool le(A a,B b)
        {
            return (static_cast<B>(a) <= b);
        }
    };
    /*
     * Parameter
     * is A int, is B int
     */
    template<bool intA,bool intB>
    struct _impl1_
    {
        template<class A,class B>
        static inline bool less_equal(A a,B b)
        {
            return a <= b;
        }
    };
    // Specialization for uint int
    template<>
    struct _impl1_<false,true>
    {
        template<class A,class B>
        static inline bool less_equal(A a,B b)
        {
            return (b >=0) && _less_equal< _le_cast_to_a_<sizeof(A),sizeof(B),std::is_signed<A>::value >::value >::le(a,b);
        }
    };
    // Specialization for int uint
    template<>
    struct _impl1_<true,false>
    {
        template<class A,class B>
        static inline bool less_equal(A a,B b)
        {
            return (a <=0) || _less_equal< _le_cast_to_a_<sizeof(A),sizeof(B),std::is_signed<A>::value >::value >::le(a,b);
        }
    };

    template<class A, class B>
    static bool less_equal(A a, B b)
    {
        return _impl1_<std::is_signed<A>::value,std::is_signed<B>::value>::less_equal(a, b);
    }

    template<class V, class T>
    static bool check(V v, T start, T end)
    {
        return less_equal(start, v) && less_equal(v, end);
    }

    void test()
    {
        volatile char c = 7;
        volatile unsigned char uc = 0xAA;
        volatile int i = -1;
        volatile unsigned int ui = 0xF000;
        volatile bool b;

        b = less_equal(c, uc);
        b = less_equal(uc, c);

        b = less_equal(c, i);
        b = less_equal(i, c);

        b = less_equal(ui, uc);
        b = less_equal(uc, ui);

        b = less_equal(i, uc);
        b = less_equal(uc, i);
        b = less_equal(ui, c);

        b = less_equal(c, ui);
        b= (c <=0) || (static_cast<unsigned int>(c) <= ui);
        b= (c <=0) || (c <= static_cast<char>(ui));
    }
}