static_cast <T>( - 1)是否生成没有numeric_limits的全1位数据的正确方法?

ein*_*ica 28 c++ bit-manipulation idiomatic

我正在一个我无法访问C++标准库的环境中编写C++代码,特别是不能访问std::numeric_limits.假设我想实施

template <typename T> constexpr T all_ones( /* ... */ )
Run Code Online (Sandbox Code Playgroud)

专注于无符号整数类型,我放在那里?具体来说,static_cast<T>(-1)够好吗?(根据我的猜测,我可以将其他类型视为无符号字符数组.)

Lea*_*ros 32

使用bitwise NOT操作~0.

T allOnes = ~(T)0;
Run Code Online (Sandbox Code Playgroud)

A static_cast<T>(-1)假设是两个补码,不可移植.如果你只关心未签名的类型,那么hvd的答案是要走的路.

工作示例:https://ideone.com/iV28u0

  • 如果`T`是'short`,那么`〜(short)0`首先将`(short)0`提升回int.然后,您最终会得到一个可能超出"short"范围的值,从而导致转换为实现定义的结果,而不必是所有位的结果.(这是两个补码不可能的,但你的答案专门试图解决其他系统的可移植性.) (10认同)
  • @Andreas好问题.这是因为整体升级,它是继承自C. C是由dmr设计的,对于编译器编写者来说很容易,因此所有可以表示为`int`的东西都被提升为int,如果它不能表示为一个`signed int`,它被提升为`unsigned int`. (4认同)
  • 关于这种方法的另一个好处是,它是**表达**.你想要所有的,这是所有零的反面.阅读它的人都知道它的作用."减一二补"方法并不具有表现力,而是依赖于实施知识. (4认同)

小智 22

专注于无符号整数类型,我放在那里?具体来说,static_cast(-1)足够好了

如果您只关心无符号类型,是的,转换-1对于所有标准C++实现都是正确的.对无符号类型的操作(包括将有符号类型转换为无符号类型)保证以模数(max + 1)工作.

  • @underscore_d确实很好地定义了C++标准.无符号类型需要完全溢出.它确实**不适用于签名类型,签名溢出未定义.我的答案是实现定义或者其中之一,但可以假设任何理智的实现都按照您的预期执行. (2认同)

Omn*_*ity 8

这种解除武装的直接方式.

T allOnes;
memset(&allOnes, ~0, sizeof(T));
Run Code Online (Sandbox Code Playgroud)

  • 这仅适用于8位字节. (13认同)
  • 我想初始化一个constexpr表达式,而不是在运行时设置一个值. (11认同)

278*_*528 7

专注于无符号整数类型,我放在那里?具体来说,static_cast(-1)足够好了

是的,这已经足够了.

但我更喜欢十六进制值,因为我的背景是嵌入式系统,而且我总是必须知道sizeof(T).

即使在桌面系统中,我们也知道以下T的大小:

uint8_t  allones8  = 0xff;
uint16_t allones16 = 0xffff;
uint32_t allones32 = 0xffffffff;
uint64_t allones64 = 0xffffffffffffffff;
Run Code Online (Sandbox Code Playgroud)