为什么QByteArray的大小是int而不是unsigned int

时间:2018-09-03 11:48:37

标签: c++ qt qbytearray

我的代码中有这样的表达式:

QByteArray idx0 = ...

unsigned short ushortIdx0;

if ( idx0.size() >= sizeof(ushortIdx0) ) {
    // Do something
}

但是我收到警告:

  

警告:有符号和无符号整数表达式[-Wsign-compare]

的比较
if ( idx0.size() >= sizeof(ushortIdx0) ) {
              ~~~~~~~~~~~~^~~~~~~~~~

为什么size()中的QByteArrayint而不是unsigned int的形式返回?我该如何安全地摆脱此警告?

4 个答案:

答案 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)) ... 并将其专门用于比较(仅用于比较)。