【发布时间】:2021-06-09 23:51:40
【问题描述】:
我意识到有一条规则可以将宽度小于int 的数字提升为更宽的类型以进行加法运算。但我无法完全解释以下print_unsafe_minus 的一个排列如何会失败。为什么只有 <unsigned, long> 示例失败了?程序员在最佳实践方面的收获是什么?
#include <fmt/core.h>
template<typename M, typename N>
void print_unsafe_minus() {
M a = 3, b = 4;
N c = a - b;
fmt::print("{}\n", c);
}
int main() {
// storing result of unsigned 3 minus 4 to a signed type
print_unsafe_minus<uint8_t, int8_t>(); // -1
print_unsafe_minus<uint16_t, int8_t>(); // -1
print_unsafe_minus<uint32_t, int8_t>(); // -1
print_unsafe_minus<uint64_t, int8_t>(); // -1
print_unsafe_minus<uint8_t, int16_t>(); // -1
print_unsafe_minus<uint16_t, int16_t>(); // -1
print_unsafe_minus<uint32_t, int16_t>(); // -1
print_unsafe_minus<uint64_t, int16_t>(); // -1
print_unsafe_minus<uint8_t, int32_t>(); // -1
print_unsafe_minus<uint16_t, int32_t>(); // -1
print_unsafe_minus<uint32_t, int32_t>(); // -1
print_unsafe_minus<uint64_t, int32_t>(); // -1
print_unsafe_minus<uint8_t, int64_t>(); // -1
print_unsafe_minus<uint16_t, int64_t>(); // -1
print_unsafe_minus<uint32_t, int64_t>(); // 4294967295
print_unsafe_minus<uint64_t, int64_t>(); // -1
}
(编辑) 另外值得注意的是——如果我们将示例扩展为包含 128 位整数,那么以下两个排列也会失败:
print_unsafe_minus<uint32_t, __int128>(); // 4294967295
print_unsafe_minus<uint64_t, __int128>(); // 18446744073709551615
【问题讨论】:
-
你知道促销规则是怎么说的吗?所有这些例子都应该可以通过精确地遵循它们来解释。当你试图解释这些情况下的规则时,你能解释一下你的解释以及它与发生的情况到底有什么不同吗?
-
@NateEldredge 如果
uint8_t和uint16_t被提升为与uint32_t相同的宽度,那么它们是否也不会像int64_t那样失败? -
程序员在最佳实践方面的收获是什么? 不要混用有符号和无符号。真的,
unsigned类型只需要按位运算。 -
only the <unsigned, long>仅来自您的代码uint32_t, int64_t失败,而不是unsigned, long -
@NathanOliver 好吧,有一些 STL 容器类型,还有它们烦人的
size_t东西!