在 C++ 中,无符号整数类型在以换行形式执行算术时具有明确定义的溢出行为。有符号整数类型不会,溢出行为是明确未定义的,取决于编译器实现。
是否有一种独立于平台的方法来执行各种算术运算以保证有符号整数类型的包装行为?理想情况下,不需要手动重新实现算术运算?
自 C++20 起,有符号整数需要具有二进制补码值表示形式。二进制补码的特殊之处在于,对于加法、减法和乘法,
signed
和 unsigned
运算在位级别上是等效的。
例如,如果你有一个 4 位整数,那么:
// unsigned perspective
2 * 9 == 18 == 2
0b0010 * 0b1001 == 0b10010 == 0b0010
// signed perspective
2 * -7 == -14 == 2
0b0010 * 0b1001 == 0b10010 == 0b0010
由于无符号整数和补码整数的换行行为是位等效的,因此您可以转换为
unsigned
,执行(明确定义的)操作,然后转换回来:
int wrapping_multiply(int x, int y) {
int(return unsigned(x) * unsigned(y));
}
或者一般来说:
template <std::integral Int>
Int wrapping_multiply(Int x, Int y) {
using Uint = std::make_unsigned_t<Int>;
return Int(Uint(x) * Uint(y));
}