Предпочитаемый способ исправить "сравнение между целым числом со знаком и без знака"? - PullRequest
2 голосов
/ 20 декабря 2010

Какой предполагается предпочтительный способ безопасного исправления предупреждений о «сравнении между целым числом со знаком и без знака»? В моем случае мне нужно сравнить некоторые переменные 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 ]

3 голосов
/ 20 декабря 2010

В этом случае вы также можете просто изменить свою константу на unsigned:

#define c 10U

или, альтернативно, используйте приведение, чтобы typeof в вашем макросе создавало переменную unsigned:

if (MAX((unsigned)c, d) > 10) {
1 голос
/ 20 декабря 2010

Я не знаю, полностью ли это верно, но моя логика гласит: Если int (со знаком) <0, это значение меньше значения без знака. В противном случае вы можете просто привести его к неподписанному целому </p>

Так что насчёт этого:

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

Это лучшая идея, однако вы не можете сделать ее «общей», я имею в виду, что вам нужно построить UINT_MAX_INT, если вы хотите изменить порядок параметров

Если вы используете Visual Studio и просто не хотите слышать предупреждение (потому что вы уверены, что оно не вызовет никаких проблем): http://msdn.microsoft.com/en-us/library/2c8f766e%28v=vs.80%29.aspx

Удачи

0 голосов
/ 23 января 2015

Я использую C ++ акции, которые «сохраняют ценность».Вопрос в том, как найти с операндом, который нужно продвигать. Сравнение между знаком без знака эквивалентно сравнению без знака после проверки, что число со знаком положительно.Если оба числа имеют одинаковый размер, я разыгрываю без знака, в противном случае я разыгрываю самый большой.Следующая реализация шаблона менее равных прекрасно работает для меня.

/*
 * 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));
    }
}
0 голосов
/ 20 декабря 2010

Моим простым предложением было бы использовать то, что вы знаете о типах 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;
}

обратите внимание на "тип заражения" (я не могу придумать лучшего слова, чтобы описать его как эффект неявный)

вы можете даже включить эту функцию.

...