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

问题描述 投票:3回答:4

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

QByteArray idx0 = ...

unsigned short ushortIdx0;

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

但是我收到了警告:

警告:有符号和无符号整数表达式之间的比较[-Wsign-compare]

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

为什么size()QByteArray被归还为int而不是unsigned int?我怎样才能安全地摆脱这个警告?

c++ qt qbytearray
4个回答
5
投票

有些人认为,几年前将unsigned类型引入C是一个坏主意。这些类型发现自己被引入到C ++中,它们深深地嵌入到C ++标准库和操作符返回类型中。

是的,按照标准,sizeof必须返回unsigned类型。

Qt开发人员采用现代的思想认为unsigned类型是一个坏主意,并且倾向于使size的返回类型成为signed类型。就个人而言,我发现它特殊。

要解决,你可以(i)接受警告,(ii)在功能期间关闭它,或者(iii)写下像

(std::size_t)idx0.size() >= sizeof(ushortIdx0)

以清晰为代价。


5
投票

为什么QByteArray的size()以int而不是unsigned int的形式返回?

我真的不知道为什么Qt为size()选择了签名回报。但是,有充分的理由使用signed而不是unsigned。

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()确实返回了有符号值,那么首先不需要修复问题。


3
投票

因为在Qt容器中(例如:QByteArray,QVector,...),有些函数可以返回负数,例如:indexOf,lastIndexOf,contains,...有些可以接受负数,例如:mid,... ;因此,为了与类兼容或甚至框架兼容,开发人员使用signed类型(int)。

您可以使用标准c ++强制转换:

if ( static_cast<size_t>(idx0.size()) >= sizeof(ushortIdx0) )

1
投票

原因是问题的重复部分,但类型不匹配的解决方案是一个有待解决的问题。对于你正在进行的那种比较,将它们分解出来可能是有用的,因为它们具有一定的可重用含义:

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)) ...

这将在概念上扩展sizeof并专门用于比较,而不是其他任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.