我正在修改对硬编码常量使用“long long”(LL
)数据类型定义的遗留代码,如下所示:
0xFFFFFFFFFFFFFFFFLL
我相信附加到常量的LL
保证此常量将被解释为long long
。
但是,我不想依赖于long long
在位数方面有任何特定的编译器相关解释。
因此,我希望我的变量声明在常量中没有LL
,而是使用:
uint64_t a = static_cast<uint64_t>(0xFFFFFFFFFFFFFFFF);
我想在编译为0xFFFFFFFFFFFFFFFF
之前,编译器不会将常量uint64_t
解释为32位整数,这会导致a
为64包含值0xFFFFFFFF
的位整数,而不是所需的值。
(我目前感兴趣的64位编译器是VS 2010,Ubuntu 12.04 LTS GCC。但是,我希望这段代码能够以任何现代编译器的方式运行。)
上述代码是否可以满足大多数或所有现代编译器的需要,因此a
的值被正确设置为根据需要包含常量0xFFFFFFFFFFFFFFFF
中的所有数字,不包括LL
在常数的末尾?
(注意:在常量的末尾包含I64
会产生编译错误。也许还有另一个令牌需要(或可以)包含在常量的末尾,以告诉编译器解释常量作为64位整数?)
(另外:甚至可能static_cast<uint64_t>
也是不必要的,因为变量显式被定义为uint64_t?)
答案 0 :(得分: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位的大小,并且该常量将被解释为64位unsigned long long int
,如您所希望的那样
答案 1 :(得分:4)
减少Andy所说的要点:如果实现有一个或多个能够表示0xFFFFFFFFFFFFFFFF
的标准整数类型,那么文字0xFFFFFFFFFFFFFFFF
有一个那些类型。
这对你来说并不重要,因为无论uint64_t
的转换结果如何都是一样的。
如果(pre-C ++ 11)实现没有任何足够大的整数类型,那么(a)程序是不正确的,所以你应该得到一个诊断; (b)可能无论如何都不会有uint64_t
。
你是正确的static_cast
是不必要的。它执行与分配给uint64_t
的转换相同的转换。有时,强制转换会抑制某些隐式整数转换所产生的编译器警告,但我认为在这种情况下,任何编译器都不太可能会警告隐式转换。通常不会有一个,因为0xFFFFFFFFFFFFFFFF
通常已经有uint64_t
类型。
顺便说一下,写static_cast<uint64_t>(-1)
或uint64_t a = -1;
可能更好。它保证等于0xFFFFFFFFFFFFFFFF
,但读者更容易看到-1
和0xFFFFFFFFFFFFFFF
之间的区别,而不是看0xFFFFFFFFFFFFFFFF
和0xFFFFFFFFFFFFFFF
之间的区别{1}}。