什么是安全地修复“有符号和无符号整数之间的比较”警告的首选方法?在我的例子中,我必须将一些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){
//...
}
但我确实很多这样的情况 - 你有什么建议来解决这个问题?
答案 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));
}
}