4

我正在修改LL对硬编码常量使用“long long”( ) 数据类型定义的遗留代码,如下所示:

0xFFFFFFFFFFFFFFFFLL

我相信LL附加到常量的保证该常量将被解释为long long.

但是,我不想long long在位数方面依赖于任何特定的编译器相关解释。

因此,我希望我的变量声明不LL使用常量,而是使用:

uint64_t a = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF);

我想认为0xFFFFFFFFFFFFFFFF编译器在转换为 之前不会将常量解释为 32 位整数uint64_t,这将导致a成为包含 value 的 64 位整数0xFFFFFFFF,而不是所需的值。

(我目前感兴趣的 64 位编译器是 VS 2010 和 Ubuntu 12.04 LTS GCC。但是,我希望这段代码能够以任何现代编译器所需的方式运行。)

对于大多数或所有现代编译器,上述代码是否会按预期工作,因此a正确设置的值可以根据需要包括常量中的所有数字,0xFFFFFFFFFFFFFFFF而不包括LL常量末尾的 ?

(注意:包含I64在常量末尾会导致编译器错误。也许有另一个标记需要(或可以)包含在常量末尾以告诉编译器将常量解释为 64 位整数?)

(另外:也许甚至static_cast<uint64_t>是不必要的,因为变量被明确定义为 uint64_t?)

4

2 回答 2

5

根据 C++11 标准的第 2.1.14/2 段:

整数文字的类型是表 6 中对应列表的第一个,其中可以表示其值

表 6 指定对于十六进制文字常量,文字的类型应为:

  • int; 或(如果不合适)
  • unsigned int; 或(如果不合适)
  • long int; 或(如果不合适)
  • unsigned long int; 或(如果不合适)
  • long long int; 或(如果不合适)
  • unsigned long long int.

如果我们做出合理的假设,0xFFFFFFFFFFFFFFFF不适合上面列表中的前 5 种类型,那么它的类型应该是unsigned long long int. 只要您使用的是 64 位编译器,就可以合理地假设这种类型的值的大小为 64 位,并且unsigned long long int如您所愿,该常量将被解释为 64-bit 。

于 2013-04-02T16:32:17.733 回答
5

为了减少安迪所说的要点:如果实现具有一种或多种能够表示的标准整数类型,0xFFFFFFFFFFFFFFFF则文字0xFFFFFFFFFFFFFFFF具有这些类型中的一种

对您而言,这并不重要,因为无论是哪一个,转换为的结果uint64_t都是相同的。

如果(C++11 之前的)实现没有足够大的整数类型,那么(a)程序格式错误,所以你应该得到一个诊断;和(b)它可能uint64_t无论如何都不会。

你是对的,这static_cast是不必要的。uint64_t无论如何,它都会执行与分配给相同的转换。有时,强制转换会抑制某些隐式整数转换的编译器警告,但我认为在这种情况下,任何编译器都不太可能警告隐式转换。通常不会有一个,因为0xFFFFFFFFFFFFFFFF通常已经有类型uint64_t

顺便说一句,写起来可能更好static_cast<uint64_t>(-1),或者只是uint64_t a = -1;。它保证等于0xFFFFFFFFFFFFFFFF,但读者更容易看到和之间的区别,-10xFFFFFFFFFFFFFFF不是看到和之间的0xFFFFFFFFFFFFFFFF区别0xFFFFFFFFFFFFFFF

于 2013-04-02T17:01:44.843 回答