【发布时间】:2012-07-15 12:19:22
【问题描述】:
在 x86/amd64 世界中,sizeof(long long) 是 8。
让我引用非常有见地的 8 岁 mail by Zack Weinberg:
斯科特·罗伯特·拉德写道:
在 64 位 AMD64 架构上,GCC 将
long long定义为 64 位,即 与long相同。鉴于某些 64 位指令(乘法)产生 128 位 结果,
long long被定义为 128 位看起来不合逻辑吗?不,有两个原因:
64位'
long long'的选择已写入ABI 大多数 LP64 型号的操作系统;我们不能单方面改变它。这实际上是正确的选择,因为它消除了畸变 这使得 '
long' 不是最广泛的基本整数类型。有 大量大量的代码写成假设sizeof(long) >= sizeof(size_t)- 这至少是潜在的 被 long long 比 long 宽的 ABI 打破。(在开发过程中这是一个极具争议的话题 C99。据我所知,从外部角度来看,'
long long' 只是在微软的压力下才标准化 出于某种原因实现了 LP64 模型。其他人都讨厌这个主意 'long' 不一定是最宽的基本整数类型。)目前的最佳做法似乎是提供“扩展积分 type"
__int128。这不存在 'long long' 的问题,因为 它不是 basic 整数类型(特别是,它不能用于size_t)。zw
long long 是最广泛的基本整数类型。在我知道的任何非死旧架构/ABI 上,它都是 64 位长的。这允许使用简单的跨平台(嗯,至少对于许多 32/64 位架构)类型定义:
typedef char s8;
typedef unsigned char u8;
typedef short s16;
typedef unsigned short u16;
typedef int s32;
typedef unsigned int u32;
typedef long long s64;
typedef unsigned long long u64;
比intXX_t 更好,因为:
- 它们在不同平台上对 64 位整数使用相同的底层类型
- 允许避免冗长的
PRId64/PRIu64
(我很清楚 Visual C++ 自 2005 年起才支持%lld/%llu)
但是这个解决方案的可移植性可以通过以下问题的答案来表达。
sizeof(long long) != 8 所在的架构/ABI 是什么?
如果您无法提供任何最近/现代的,那么请继续使用旧的,但前提是它们仍在使用中。
【问题讨论】:
-
顺便说一句,
typedef int s32在 16 位int的实现上失败,其中有一些微控制器正在运行。显然这与long long无关,这意味着您对s32的计划与您提出的问题无关:-) 但我认为您更有可能绊倒s32而不是s64. -
@SteveJessop:当然。问题仅与
long long有关,但出于通常目的,我确实只关心char、short和int分别为 8 位、16 位和 32 位长的平台。 -
假设
sizeof(long)>=sizeof(size_t)真的很普遍吗?我一直认为相反... -
@dreamlax:我不熟悉那场辩论,但我认为当时有代码将大小和偏移量存储在
unsigned long中。我不确定这实际上是否比在int中存储long的Windows 代码更好,这阻止了MS 实现LP64。但实际上 C89 确实保证size_t是“整数类型”,而 C89 中的“整数类型”只是标准中要求的基本类型。因此,C99 允许size_t成为比unsigned long更大的类型是一个突破性的变化,因为 C89 禁止这样做。 -
long long不是微软的选择。由于现有实践以及在流行的 ABI 已经将long作为 32 位的 32 位系统上需要 64 位类型,因此它被标准化。