在64位数据模型上指定64位无符号整数字面量

33

由于存在各种类型的64位数据模型(LLP64 / IL32P64,LP64 / I32LP64,ILP64,SILP64),因此指定64位无符号整数文字的标准符合方式是什么?

指定ULL后缀是否足够?还是会导致在某些数据模型上将文字解释为128位?


1
如果你将整数分配给 uint64_t,那应该没问题。 - kennytm
@KennyTM:只能到2^32 - 1,超过这个数字可能会出问题... - DevSolar
@DevSolar:我的意思是带有ULL后缀的整数,对于值高达18446744073709551615肯定有效。 - kennytm
@KennyTM:啊...对,当然。 - DevSolar
如果你的字面量被解释为128位,这会有问题吗? - jalf
4个回答

42

如果你有的话,应该使用 <cstdint> / <stdint.h>。这将会给你:

  • uint64_t 是一个无符号整数类型,长度为 64 位
  • UINT64_C() 是创建 uint64_t 类型常量的宏,它会自动添加正确的后缀。

3
在C++中,UINT64_C是否保证可用?(问题涉及C++而非C99) - jalf
@jalf 很好的观点,谢谢!我不确定,但似乎是这样。我重写并更改了链接。 - unwind
长时间之后回到这个问题...让我挑刺一下,UNIT64_C 解析为 uint_least64_t,而不是 uint64_t。;-) - DevSolar

2
据我所知,没有一种方法可以后缀一个整数字面量到特定的位宽;你唯一的选择是l、ul、ll和ull。
如果你对此很担心,你需要在字面量周围包上一个 #if 来检查long / long long的大小。
但是,正如 KennyTM 上面指出的那样,只要您的字面量在64位范围内并分配给64位值,它本身是否为64或128位不太重要,对吗?

这会不会导致编译器抱怨我正在将需要更大位宽的整数分配给一个较小的整数(截断警告)? - Zach Saw
2
使用大写后缀来保持有符号字面量的可读性:1L,1LL而不是1l,1ll。 - pixelgrease

2

大多数情况下,这并不重要。如果您没有给整数字面值添加后缀,其类型将由其值确定。如果编译器具有32位的unsigned long和64位的unsigned long long,那么一个无符号值如果太大而无法容纳在unsigned long中,但不太大到无法容纳在unsigned long long中,则其类型为unsigned long long


1

C和C++没有标准化的32/64/128位变量类型。例如,某些系统上的long是32位,而在其他系统上则是64位。这很烦人,但大多数操作系统确实提供了一些更好的typedefs来帮助您选择所需的确切类型,例如uint32等。

这是一个好的configure脚本的工作:确定系统提供的内容,测试其是否有效,并帮助您选择适合您正在运行的正确架构的正确类型。


3
C和C++在<stdint.h><cstdint>头文件中提供了给定大小的标准化变量类型。它们有像uint32_t这样的名称。 - amaurea
1
@amaurea - 像 uint32_t 这样的名称在没有这些确切大小的系统上是不可用的。在几乎所有情况下,uint_least32_t 等会是更好的选择。 - Pete Becker
1
@Pete Becker 没有 uint32_tuint64_t 的系统几乎不可能找到,它们属于字节不是8位长和其他奇特系统的同一类别,不是吗? - amaurea
1
@amaurea - 在你找到一个之前,它们是不可能被找到的,然后你必须找到代码中所有不合理的假设并修复它们。许多系统没有8位字节;它们不是奇特之处,而是真实世界的系统。DSP是一个典型的例子。 - Pete Becker
作为一个大型、高度可移植和非常系统特定的软件包的作者,我可以告诉你,没有 uint32_t 的系统仍然存在。只是你在桌面机器上安装的标准发行版上没有而已。许多嵌入式版本的东西仍然没有甚至标准头文件。我真希望它们都有。我们的配置脚本会费尽心思地检查我们需要使用的每个 uint*_t,并在使用 sizeof(long) 等测试变量类型的实际长度后自己定义它们。 - Wes Hardaker
1
...但这并没有回答问题。:) 无论uint64_t是否存在,它都不能帮助想要编写64位整数字面量的人。 - jalf

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