c++ - 为什么:不同符号的整数的比较有时只会发生?
问题描述
解决方案:检查人们是否安装了自定义编译器。
解决方案扩展:我只在服务器上编译,而不是在我的机器上本地编译,当我这样做时,我可以重现@AK 的答案服务器上的编译是 g++ 和 clang++ 的自定义版本。很抱歉浪费了人们的时间:(编译器将被删除,我将安装一次官方。
这更像是一个好奇的问题。当您与数字类型进行比较时,让我们说int
,size_t
有时会出现此警告:error: comparison of integers of different signs:
,使用-Wsign-compare
and时-Werror
,没有-Werror
is 显示为警告。
但是,在开始与同事合作后,我注意到尚不清楚错误是否会真正出现。我注意到这一点的原因是我们的写作方式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_type
或unsigned long
. 该int i
方法导致错误。
这对我来说很奇怪,因为我希望这两种情况都会引发错误。有人可以解释为什么会这样吗?我已经能够用 g++ 和 clang++ 重现这个
编译标志的完整列表是-std=c++17 -g -Wall -Wextra -O3
,错误由 clang 和 gcc 显示是由于-Werror
and-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;
}
解决方案
我无法用 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
禁用了警告?
推荐阅读
- javascript - 将值修补到子组件时如何将反应形式标记为 Pristine?
- c++ - Win32 ReadProcessMemory API 的问题
- html - 如何在角度中禁用matchip
- apache-spark - Spark Structured Streaming:加入跨越数年的流
- excel - 在 VBA 中的 FIND 中引用单元格
- java - 如何在 Java 中按日期对 ArrayList 的元素进行排序?
- ios - 在 SwiftUI 中设置视图的默认方向
- r - 循环瑞利测试以找到最高值
- python - 为什么 pylint 反对 deepcopy 上的受保护成员?
- ios - 即使货币符号为空白,Swift NumberFormatter 也会将 Unicode 空格附加到货币字符串