代码之家  ›  专栏  ›  技术社区  ›  Megidd

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

  •  3
  • Megidd  · 技术社区  · 6 年前

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

    QByteArray idx0 = ...
    
    unsigned short ushortIdx0;
    
    if ( idx0.size() >= sizeof(ushortIdx0) ) {
        // Do something
    }
    

    但我得到了警告:

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

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

    为什么? size() QByteArray 返回为 int unsigned int ? 我怎样才能安全地摆脱这个警告呢?

    4 回复  |  直到 6 年前
        1
  •  5
  •   Bathsheba    6 年前

    有些人觉得 unsigned 那么多年前输入C是个坏主意。这些类型本身被引入到C++中,它们深深地嵌入C++标准库和操作符返回类型中。

    对, sizeof 按照标准,必须返回 未签名 类型。

    Qt开发人员采用了 未签名 类型是一个坏主意,而青睐,而不是使回报类型的 size signed 类型。我个人觉得这很特别。

    要解决这个问题,您可以(i)接受警告,(ii)在函数执行期间关闭警告,或者(iii)编写类似的代码

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

    以牺牲清晰度为代价。

        2
  •  5
  •   463035818_is_not_an_ai    6 年前

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

    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

    但是,如果容器是空的 一些_容器.尺寸() - 1 将静默地(无符号溢出定义良好)变成无符号类型的最大值。因此,它不是避免越界访问,而是导致您可以获得的最大越界。

    注意这个问题有简单的解决方法,但是如果 大小()

        3
  •  3
  •   AshkanVZ    6 年前

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

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

    if ( static_cast<size_t>(idx0.size()) >= sizeof(ushortIdx0) )
    
        4
  •  1
  •   Kuba hasn't forgotten Monica    6 年前

    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