【问题标题】:Preferred way to fix "comparison between signed and unsigned integer" warnings?修复“有符号整数和无符号整数之间的比较”警告的首选方法?
【发布时间】:2011-05-28 01:44:27
【问题描述】:

什么是安全修复“有符号整数和无符号整数之间的比较”警告的首选方法?就我而言,我必须将一些 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){
  //...
}

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

【问题讨论】:

  • 这个具体的例子真的会发出警告吗?我已经认为这个警告很烦人,但如果它不能告诉签名的操作数是一个正常数,因此升级为无符号时没有改变,我只能说你应该向 gcc 团队提交一个错误报告并关闭警告。千万不要弄乱你的代码来解决这个问题......
  • 顺便说一句,我敢肯定,如果你用标准版本替换满是 gcc 扩展的丑陋的 MAX 宏,它就会消失。没有人期望 MINMAX 宏不会多次评估其参数。如果不出意外,将__a__b 重命名为合法的变量名。双下划线前缀的名称是为实现保留的。

标签: c integer unsigned signed


【解决方案1】:

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

#define c 10U

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

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

【讨论】:

    【解决方案2】:

    我不知道这是否完全正确,但我的逻辑是这样的: 如果int(有符号)

    那么这个呢:

    #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

    祝你好运

    【讨论】:

    • 您可以使用更多 gcc 扩展使其通用。使用#define IS_UNSIGNED(A) ((__typeof(A)__)-1 &gt; 0) 可以轻松测试哪些参数未签名。
    【解决方案3】:

    我的简单建议是使用您对有符号和无符号 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;
    }
    

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

    你甚至可以内联这个函数。

    【讨论】:

    • 它应该被称为一个奇怪的名字,例如'max_si_ui',以避免有人误认为它是正常的'max'并用负整数作为第二个参数来调用它。否则,这通常是混合比较问题的一个很好的解决方案 - 但我不确定它在目前的情况下是否有帮助。
    【解决方案4】:

    我使用“保值”的 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));
        }
    }
    

    【讨论】:

    • C 和 C++ 是两种不同的语言。这个问题是关于 C 的!
    猜你喜欢
    • 2013-11-11
    • 2011-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-15
    • 2014-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多