如何输入int64_t/uint64_t常量?

24
我想做的是定义一个常量等于2^30(我可能会将其更改为类似于2^34的东西,因此我更喜欢具有大于32位的空间)。以下最小(?)示例为什么无法编译?
#include <stdint.h>
// test.cpp:4:33: error: expected primary-expression before numeric constant
// test.cpp:4:33: error: expected ')' before numeric constant
const uint64_t test = (uint64_t 1) << 30;
//const uint64_t test1 = (uint64_t(1)) << 30;// this one magically compiles! why?

int main() { return 0; }
3个回答

45

您可以使用宏:

UINT64_C
为了定义一个64位无符号整数字面量,cstdint头文件提供了宏来定义特定大小的整数字面量。在 18.4.1Header synopsis 中可以看到:该头文件还定义了许多形式为以下所示的宏:[U]INT{8 16 32 64 MAX}_C,以及一些函数宏。要了解它们的工作原理,需要回到 C99 草案标准的 7.18.4.1Macros for minimum-width integer constants 中,其中指出:"如果 uint_least64_t 是 unsigned long long int 的名称,则 UINT64_C(0x123) 可能会扩展为整数常量 0x123ULL。" 这是定义64位整数常量表达式的正确方式。不幸的是,这一点没有在 cpprefernce 上记录,但是 cplusplus.composix reference for stdint.h 都记录了 cstdint头文件的这一特性。

1
虽然这个答案与原帖的直接相关性不如被采纳的答案,但它更具有普适性,因此应该成为被采纳的答案。 - Todd Freed
2
我还会包含这个链接作为参考:http://pubs.opengroup.org/onlinepubs/009695399/basedefs/stdint.h.html - Todd Freed
1
@ToddFreed 好的,我会去查看一下那个参考链接。最近我收到了一些赞同票,我在想是否有外部网站链接到了这篇内容。 - Shafik Yaghmour

16
您要查找的语法是:

您要查找的语法是:

const uint64_t test = 1ULL << 30;

后缀ULL用于至少有64位宽度的无符号整型字面量。

3
这不是一种“简短表示法”,而是指定大小的数字文字的唯一表示法。使用强制类型转换方法最终会在第一次编译器通过时被优化为此表示法(对于任何合理的编译器而言)。 - Zac Howland
16
这是不正确的。如果你使用uint64_t来定义整数类型,你应该使用相应的文字记法,即UINT64_C(arg)。"ULL"后缀恰好对应于"unsigned long long",而uint64_t则可能会因平台而异。这种平台无关性是你首先使用uint64_t的唯一原因。 - Todd Freed
1
@ToddFreed 你知道 UINT64_C 是一个宏,它会扩展成 value##ULL 吗?换句话说,它做的事情与我在这里发布的内容完全相同。声称它是“不正确的”是事实上错误的。 - Zac Howland
10
在一个平台上,如果uint64_t等于unsigned long long,那么UINT64_C将扩展为ULL。在一个平台上,如果uint64_t等于unsigned long,那么UINT64_C将扩展为UL。请参阅stdint.h。 - Todd Freed
3
如果你只关心那些uint64_t等于unsigned long long的平台,那么你的解决方案是可行的。但那为什么不一开始就使用unsigned long long作为数据类型呢?你最初提出的声明是错误的,“ULL是用于无符号64位整数”的说法是错误的。一个正确的说法应该是:ULL是用于无符号长整型整数的。 - Todd Freed
显示剩余4条评论

6

(uint64_t 1)不是有效的语法。在类型转换时,可以使用uint64_t(1)(uint64_t) 1。注释掉的示例之所以有效,是因为它遵循了正确的类型转换语法,下面的代码也同样适用:

const uint64_t test = ((uint64_t)1) << 30;

编辑:虽然这直接回答了问题,但请参见Shafik Yaghmour的答案,了解如何正确定义具有特定大小的整数常量。


是的,你说得对。由于某种原因,我忘记在类型周围加上括号了,而这确实是C风格转换符号所必需的。 - fiktor
我通常只使用大小写字面后缀 auto value = 1ui64 << 30; (尽管遗憾的是,似乎只有MSVC支持类型后缀,而clang、gcc和Intel编译器在Godbolt上尝试后只支持ULL - 哦,好吧) - Dwayne Robinson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接