比较有符号性不同的整数
compare integers with different signedness
我写了一些程序来测试我的怀疑。它包含超级超可靠的函数,在我看来是:)
,称为less
,用于比较整数。对于某些类型的组合,它会产生与结果不同的结果,从而产生C++。当这种情况发生时,就会出现错误,你可以在屏幕上看到。
#include <iostream>
#include <iomanip>
#include <type_traits>
#include <limits>
#include <typeinfo>
#include <cstdlib>
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wtype-limits"
template< typename T, typename U >
inline
bool less(T const & lhs, U const & rhs)
{
if (std::is_signed< T >::value && std::is_unsigned< U >::value) {
if (lhs < 0) {
return true;
} else if (rhs > std::numeric_limits< T >::max()) {
return true;
} else {
return static_cast< T >(lhs) < rhs;
}
} else if (std::is_unsigned< T >::value && std::is_signed< U >::value) {
if (rhs < 0) {
return false;
} else if (lhs > std::numeric_limits< T >::max()) {
return false;
} else {
return lhs < static_cast< T >(rhs);
}
} else {
return lhs < rhs;
}
}
#pragma GCC diagnostic warning "-Wtype-limits"
#pragma GCC diagnostic warning "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wsign-compare"
#pragma GCC diagnostic ignored "-Wtype-limits"
template< typename U, typename S >
void test()
{
std::cout << typeid(U).name() << " vs " << typeid(S).name() << std::endl;
static_assert(std::is_unsigned< U >::value && std::is_signed< S >::value, "signedness violated");
static_assert(sizeof(U) != sizeof(S), "size should not be the same");
U const x(std::numeric_limits< U >::max() - 2);
S const y(-1);
S const z(std::numeric_limits< S >::min());
std::cout << std::boolalpha << (less(x, y) == (x < y)) << std::endl
<< std::boolalpha << (less(y, x) == (y < x)) << std::endl
<< std::boolalpha << (less(y, z) == (y < z)) << std::endl
<< std::boolalpha << (less(z, y) == (z < y)) << std::endl
<< std::boolalpha << (less(x, z) == (x < z)) << std::endl
<< std::boolalpha << (less(z, x) == (z < x)) << std::endl
<< std::endl;
}
#pragma GCC diagnostic warning "-Wtype-limits"
#pragma GCC diagnostic warning "-Wsign-compare"
int main()
{
using namespace std;
test< uint8_t, int16_t >();
test< uint8_t, int32_t >();
test< uint8_t, int64_t >();
test< uint16_t, int8_t >();
test< uint16_t, int32_t >();
test< uint16_t, int64_t >();
test< uint32_t, int8_t >();
test< uint32_t, int16_t >();
test< uint32_t, int64_t >();
test< uint64_t, int8_t >();
test< uint64_t, int16_t >();
test< uint64_t, int32_t >();
return EXIT_SUCCESS;
}
我使用以下脚本编译(bash s.sh 2>&1 | tee s.log
)程序:
#!/usr/bin/env sh
set -o errexit
set -o verbose
g++ -std=gnu++11 -m64 s.cpp -o s64
g++ -std=gnu++11 -m32 s.cpp -o s32
MINGWDIR=/c/mingw64
PATH=/usr/bin:${MINGWDIR}/bin:/c/Windows/system32:${MINGWDIR}/x86_64-w64-mingw32/lib32 ./s64 2>&1 | tee s64.log | grep -c false
PATH=/usr/bin:${MINGWDIR}/bin:/c/Windows/system32:${MINGWDIR}/x86_64-w64-mingw32/lib32 ./s32 2>&1 | tee s32.log | grep -c false
diff s32.log s64.log
结果(s.log
)脚本给出以下内容:
g++ -std=gnu++11 -m64 s.cpp -o s64
g++ -std=gnu++11 -m32 s.cpp -o s32
MINGWDIR=/c/mingw64
PATH=/usr/bin:${MINGWDIR}/bin:/c/Windows/system32:${MINGWDIR}/x86_64-w64-mingw32/lib32 ./s64 2>&1 | tee s64.log | grep -c false
10
PATH=/usr/bin:${MINGWDIR}/bin:/c/Windows/system32:${MINGWDIR}/x86_64-w64-mingw32/lib32 ./s32 2>&1 | tee s32.log | grep -c false
10
diff s32.log s64.log
正如您所看到的,结果是相同的(对于x32和x64平台)。有些测试失败了。为什么会发生这种情况?我的程序错了,或者我对C++的了解很少?
您正在测试基本的operator <
函数是否与less
函数相同。事实并非如此。
您的函数解释了有符号/无符号的不匹配,并给出了数学上正确的答案。
当有符号/无符号不匹配时,基本C++运算符将把有符号值转换为无符号值。
相关文章:
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 检查TCHAR数组输入是否为带符号整数C++
- 如何打印boost多精度128位无符号整数
- C++模板函数,用于比较任何无符号整数和有符号整数
- 在数字之间插入 + 或 - 符号以使其等于整数
- 为什么:不同符号的整数比较只是偶尔发生?
- 将超出范围的整数分配给有符号字符类型
- 为什么乘以常量有符号整数分数没有优化?
- 如何解决隐式转换丢失整数精度:'size_t'(又名"无符号长")到'int'警告?
- 在线程中读取无符号整数时,c++ 位是否以原子方式切换?
- FlatBuffers/Protobuf 中是否有支持任意 24 位有符号整数定义的可移植二进制序列化架构?
- C++11 标准是否保证零值有符号整数的一元减号为零?
- 整数类型应该显式转换(例如"int"到"无符号")还是只会增加混乱?
- Constexpr 可变参数模板,用于对无符号整数进行重新排序
- AVX2 整数乘以有符号 8 位元素,产生有符号 16 位结果?
- 为什么 Clang 和 GCC 中两个无符号整数之和的结果类型不同
- 使用192/256位整数求和无符号64位整数向量的点积的最快方法
- 为什么对无符号字符进行算术运算会将它们提升为有符号整数
- 从 std::string 转换为 const 无符号整数
- 矢量浮点到整数/符号转换