我的代码中有这样的表达式:
QByteArray idx0 = ...
unsigned short ushortIdx0;
if ( idx0.size() >= sizeof(ushortIdx0) ) {
// Do something
}
但是我收到警告:
警告:有符号和无符号整数表达式[-Wsign-compare]
的比较if ( idx0.size() >= sizeof(ushortIdx0) ) { ~~~~~~~~~~~~^~~~~~~~~~
为什么size()
中的QByteArray
以int
而不是unsigned int
的形式返回?我该如何安全地摆脱此警告?
答案 0 :(得分:5)
有些人认为,所有年前,在C中引入unsigned
类型都是一个坏主意。此类类型被发现已引入C ++中,并被深深地嵌入C ++标准库和操作符返回类型中。
是的,sizeof
必须按照标准返回unsigned
类型。
Qt开发人员采用了现代的思想,认为unsigned
类型不是一个好主意,而是倾向于将size
的返回类型设为signed
类型。我个人认为它是特质的。
要解决此问题,您可以(i)保留警告,(ii)在功能持续时间内将其关闭,或(iii)编写类似的内容
(std::size_t)idx0.size() >= sizeof(ushortIdx0)
以牺牲清晰度为代价。
答案 1 :(得分:5)
为什么QByteArray的size()返回为整数而不是无符号整数?
我真的不知道Qt为什么选择size()
的签名收益。但是,有充分的理由使用签名而不是未签名。
一个unsigned size()
惨败的臭名昭著的例子是这个看起来很无辜的循环:
for (int i = 0; i < some_container.size() - 1; ++i) {
do_somehting(some_container[i] , some_container[i+1] );
}
使循环体对两个元素进行操作并不少见,在这种情况下,仅迭代到some_container.size() - 1
似乎是一个有效的选择。
但是,如果容器为空,some_container.size() - 1
将无提示(定义了无符号的溢出)变成无符号类型的最大值。因此,与其避免越界访问,不如说是导致您可以得到的最大越界。
请注意,有解决此问题的简便方法,但是如果size()
返回一个带符号的值,那么就没有需要首先解决的问题。
答案 2 :(得分:3)
因为在Qt容器中(例如:QByteArray,QVector等),有些函数可以返回负数,例如:indexOf,lastIndexOf,contains,...,有些函数可以接受负数,例如:mid, ...;因此,为了与类兼容甚至与框架兼容,开发人员使用带符号的类型(int)。
您可以使用标准的c ++强制转换:
if ( static_cast<size_t>(idx0.size()) >= sizeof(ushortIdx0) )
答案 3 :(得分:1)
原因是问题的重复部分,但是类型不匹配的解决方案是一个有效的问题。对于您正在进行的比较,将它们排除在外可能很有用,因为它们具有一定的可重用意义:
put
希望您只会进行几种这样的比较,对于DRY(不要重复自己)最有意义,并且不要使用强制转换的复制面,而应使用专用于此任务的函数-也可以表达原始比较的目的。这样,您就可以轻松集中处理您可能希望处理的所有极端情况,即template <typename T> bool fitsIn(const QByteArray &a) {
return static_cast<int>(sizeof(T)) <= a.size();
}
template <typename T> bool fitsIn(T, const QByteArray &a) {
return fitsIn<T>(a);
}
if (fitsIn(ushortIdx0, idx0)) ...
时。
另一种方法是定义一个新的类型来包装sizeof(T) > INT_MAX
并使其适应您需要使用的类型:
size_t
从概念上讲,这将扩展class size_of {
size_t val;
template <typename T> static typename std::enable_if<std::is_signed<T>::value, size_t>::type fromSigned(T sVal) {
return (sVal > 0) ? static_cast<size_t>(sVal) : 0;
}
public:
template <typename T, typename U = std::enable_if<std::is_scalar<T>::value>::type>
size_of(const T&) : val(sizeof(T)) {}
size_of(const QByteArray &a) : val(fromSigned(a.size())) {}
...
bool operator>=(size_of o) const { return value >= o.value; }
};
if (size_of(idx0) >= size_of(ushortIdx0)) ...
并将其专门用于比较(仅用于比较)。