在没有 numeric_limits 的情况下,static_cast<T>(-1) 是生成全一位数据的正确方法吗?
Is static_cast<T>(-1) the right way to generate all-one-bits data without numeric_limits?
我在无法访问 C++ 标准库的环境中编写 C++ 代码,特别是无法访问 std::numeric_limits
。假设我要实现
template <typename T> constexpr T all_ones( /* ... */ )
专注于无符号整数类型,我在那里放什么?具体来说,static_cast<T>(-1)
够好吗? (其他类型我可以根据我猜的大小将其视为无符号字符数组。)
在 0
上使用 bitwise NOT
运算符 ~
。
T allOnes = ~(T)0;
A static_cast<T>(-1)
采用不可移植的二进制补码。如果您只关心无符号类型, 是正确的选择。
Focusing on unsigned integral types, what do I put there? Specifically, is static_cast(-1) good enough
如果您只关心无符号类型,是的,转换 -1
对于所有标准 C++ 实现都是正确的。对无符号类型的操作,包括有符号类型到无符号类型的转换,保证以模数 (max+1) 工作。
这种非常直接的方式。
T allOnes;
memset(&allOnes, ~0, sizeof(T));
Focusing on unsigned integral types, what do I put there?
Specifically, is static_cast(-1) good enough
是的,已经足够好了。
但我更喜欢十六进制值,因为我的背景是嵌入式系统,而且我一直都必须知道 sizeof(T)。
即使在桌面系统中,我们也知道以下 T 的大小:
uint8_t allones8 = 0xff;
uint16_t allones16 = 0xffff;
uint32_t allones32 = 0xffffffff;
uint64_t allones64 = 0xffffffffffffffff;
另一种方式是
static_cast<T>(-1ull)
这会更正确并且适用于任何有符号整数格式,无论 1 的补码、2 的补码或符号大小如何。您也可以使用 static_cast<T>(-UINTMAX_C(1))
因为unary minus of an unsigned value定义为
The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand."
因此-1u
总是return在unsigned int
中的全1位数据。 ll
后缀是为了使其适用于任何比 unsigned long long
窄的类型。 C++ 中没有 extended integer types(还),所以这应该没问题
然而,表达意图更清晰的解决方案是
static_cast<T>(~0ull)
我在无法访问 C++ 标准库的环境中编写 C++ 代码,特别是无法访问 std::numeric_limits
。假设我要实现
template <typename T> constexpr T all_ones( /* ... */ )
专注于无符号整数类型,我在那里放什么?具体来说,static_cast<T>(-1)
够好吗? (其他类型我可以根据我猜的大小将其视为无符号字符数组。)
在 0
上使用 bitwise NOT
运算符 ~
。
T allOnes = ~(T)0;
A static_cast<T>(-1)
采用不可移植的二进制补码。如果您只关心无符号类型,
Focusing on unsigned integral types, what do I put there? Specifically, is static_cast(-1) good enough
如果您只关心无符号类型,是的,转换 -1
对于所有标准 C++ 实现都是正确的。对无符号类型的操作,包括有符号类型到无符号类型的转换,保证以模数 (max+1) 工作。
这种非常直接的方式。
T allOnes;
memset(&allOnes, ~0, sizeof(T));
Focusing on unsigned integral types, what do I put there? Specifically, is static_cast(-1) good enough
是的,已经足够好了。
但我更喜欢十六进制值,因为我的背景是嵌入式系统,而且我一直都必须知道 sizeof(T)。
即使在桌面系统中,我们也知道以下 T 的大小:
uint8_t allones8 = 0xff;
uint16_t allones16 = 0xffff;
uint32_t allones32 = 0xffffffff;
uint64_t allones64 = 0xffffffffffffffff;
另一种方式是
static_cast<T>(-1ull)
这会更正确并且适用于任何有符号整数格式,无论 1 的补码、2 的补码或符号大小如何。您也可以使用 static_cast<T>(-UINTMAX_C(1))
因为unary minus of an unsigned value定义为
The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand."
因此-1u
总是return在unsigned int
中的全1位数据。 ll
后缀是为了使其适用于任何比 unsigned long long
窄的类型。 C++ 中没有 extended integer types(还),所以这应该没问题
然而,表达意图更清晰的解决方案是
static_cast<T>(~0ull)