首页 > 解决方案 > 为什么:不同符号的整数的比较有时只会发生?

问题描述

解决方案:检查人们是否安装了自定义编译器。

解决方案扩展:我只在服务器上编译,而不是在我的机器上本地编译,当我这样做时,我可以重现@AK 的答案服务器上的编译是 g++ 和 clang++ 的自定义版本。很抱歉浪费了人们的时间:(编译器将被删除,我将安装一次官方。

这更像是一个好奇的问题。当您与数字类型进行比较时,让我们说intsize_t有时会出现此警告:error: comparison of integers of different signs:,使用-Wsign-compareand时-Werror,没有-Werroris 显示为警告。

但是,在开始与同事合作后,我注意到尚不清楚错误是否会真正出现。我注意到这一点的原因是我们的写作方式for-loops。我同事的风格:

for (int i = 0; i < collection.size(); i++)

和我的风格

for (size_t i = 0; i < collection.size(); ++i)

如果集合是标准集合(即向量、映射),则两者都不会抛出和错误,其中size_t是返回大小的类型。但是,如果我们使用pqxx::result具有大小类型pqxx::result::size_typeunsigned long. 该int i方法导致错误。

这对我来说很奇怪,因为我希望这两种情况都会引发错误。有人可以解释为什么会这样吗?我已经能够用 g++ 和 clang++ 重现这个

编译标志的完整列表是-std=c++17 -g -Wall -Wextra -O3,错误由 clang 和 gcc 显示是由于-Werrorand-Wsign-compare和完整的错误:comparison of integers of different signs: 'int' and 'unsigned long' [-Wsign-compare]

我们都通过提供的 g++ 9.3.1 20200408 和 clang++ 9.0.1 获得了这个,两者都来自 Ubuntu 软件包 repo。

最小的工作示例:

#include <ctime>
#include <algorithm>
#include <cstdint>
#include <vector>

int main(void)
{
    srand(static_cast<uint32_t>(time(0)));
    std::vector<uint8_t> data(1024);
    std::generate(std::begin(data), std::end(data), rand);


    // No problem 
    for (size_t i = 0; i < data.size(); ++i)
    {}

    // No problem 
    for (int i = 0; i < data.size(); ++i)
    {}

    unsigned long x = data.size();  
    // Problem
    for (int i = 0; i < x; ++i)
    {}
        
    return 0; 
}

标签: c++

解决方案


我无法用 g++ 8.1.0 重现您的问题。如果我尝试将 int(默认签名)与 size_t(默认未签名)进行比较,我总是会收到错误/警告。这是可以预料的,因为 int 默认定义为已签名:https ://de.cppreference.com/w/cpp/language/types

如果我使用一个使用 unsigned long 作为大小类型的类,也会发生同样的情况(当然)。请参阅以下示例和编译器输出:

#include <vector>
#include <iostream>
#include <initializer_list>

class MyClass{
public:
  MyClass(){

  }
  MyClass(std::initializer_list<int> il): _size(std::distance(il.begin(), il.end())){
    _vals = new int[_size];
    std::copy(il.begin(), il.end(), _vals);
  }

  ~MyClass(){
    delete(_vals);
  }

  typedef unsigned long size_type ;

  int& operator[](size_type index){
    if (index >= _size) { 
        throw "Index out of range"; 
    } 
    return _vals[index]; 
  }

  size_type size(){
    return _size;
  }

private:
  int * _vals;
  size_type _size;
};

int main() {
  std::vector<int> collection = {1,2};
  MyClass my_class = {3,4};

  for(int i=0; i < collection.size(); i++){
    std::cout << collection[i] << std::endl;
  }

  for(size_t i=0; i < collection.size(); i++){
    std::cout << collection[i] << std::endl;
  }

  for(int i=0; i < my_class.size(); i++){
    std::cout << my_class[i] << std::endl;
  }

  for(MyClass::size_type i=0; i < my_class.size(); i++){
    std::cout << my_class[i] << std::endl;
  }

  return 0;
}

这导致以下编译器输出:

# g++ -Wall .\main.cpp -o main
.\main.cpp: In function 'int main()':
.\main.cpp:41:18: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'unsigned int'} [-Wsign-compare]
   for(int i=0; i < collection.size(); i++){
                ~~^~~~~~~~~~~~~~~~~~~
.\main.cpp:49:18: warning: comparison of integer expressions of different signedness: 'int' and 'MyClass::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   for(int i=0; i < my_class.size(); i++){
                ~~^~~~~~~~~~~~~~~~~

也许您正在编译没有 -Wsign-compare并且在您的第二个示例中您正在编译 -Wsign-compare?也许您在第一个示例中错误地使用-Wno-sign-compare-w禁用了警告?


推荐阅读