【问题标题】:Is `long` guaranteed to be at least 32 bits?`long` 是否保证至少为 32 位?
【发布时间】:2011-05-18 19:17:51
【问题描述】:

通过阅读 C++ 标准,我一直理解 C++ 中整数基本类型的大小如下:

sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int)

我从 3.9.1/2 推断出这个:

  1. 有四种有符号整数类型:“signed char”、“short int”、 “int”和“long int”。在这份名单中, 每种类型至少提供尽可能多的 存储在它之前的那些 列表。普通整数具有自然大小 建议的架构 执行环境

此外,char 的大小由 3.9.1/ 描述为:

  1. [...] 大到足以存储实现的基本字符集的任何成员。

1.7/1 更具体地定义了这一点:

  1. C++ 内存模型中的基本存储单元是字节。一个字节至少大到足以包含基本执行字符集的任何成员,并且由连续的位序列组成,位的数量由实现定义。

这使我得出以下结论:

1 == sizeof(char) <= sizeof(short int) <= sizeof(int) <= sizeof(long int)

sizeof 告诉我们该类型有多少字节。此外,实现定义了一个字节中有多少位。我们大多数人可能习惯于处理 8 位字节,但标准说一个字节中有 n 位。


this post,Alf P. Steinbach 说:

long 保证(至少)32 位。

这与我所理解的 C++ 标准中基本类型的大小完全不同。通常我会认为这是一个错误的初学者,但由于这是 Alf,我认为值得进一步调查。

那么,你说什么?标准是否保证 long 至少为 32 位?如果是这样,请具体说明如何做出此保证。我只是没看到。

  1. C++ 标准明确规定,要了解 C++,您必须了解 C (1.2/1) 1

  2. C++ 标准隐式定义了 long 可以容纳的值的最小限制为 LONG_MIN-LONG_MAX 2

因此,无论long 有多大,它都必须足够大以将 LONG_MIN 保持到 LONG_MAX。

但是 Alf 和其他人特定长必须至少为 32 位。这就是我要建立的。 C++ 标准明确表示未指定字节中的位数(可能是 4、8、16、42)那么连接如何从能够容纳数字LONG_MIN-LONG_MAX 到至少 32 位?


(1) 1.2/1:以下引用文件对于本文件的应用是必不可少的。对于注明日期的参考文献,仅引用的版本适用。对于未注明日期的参考文献,适用参考文件的最新版本(包括任何修订)。

  • ISO/IEC 2382(所有部分),信息技术 - 词汇
  • ISO/IEC 9899:1999,编程语言 - C
  • ISO/IEC 10646-1:2000,信息技术 - 通用多字节编码字符集 (UCS) - 第 1 部分:体系结构和基本多语言平面

(2)在&lt;climits&gt;中定义为:

LONG_MIN -2147483647 // -(2^31 - 1)
LONG_MAX +2147483647 //   2^31 - 1

【问题讨论】:

  • @Mark:肯定有机器只能处理大于 8 位的数量,例如32 位字,通常使用 char == int == long == 32 位。
  • @Mark Storer:现在不是 8 位的字节很少见,但过去有各种各样的系统。具有 36 位字的计算机将具有 9 位字节。具有 60 位字的旧 CDC Cyber​​ 系统如果有 C 编译器,则必须有 60 位字节(这会导致问题),但通常字符占用 6 位(如果有 6/12 位方案你真的想要小写)。
  • @Mark Storer:德州仪器有一系列带有 C++ 编译器和 16 位字节的 DSP。或者他们曾经有,几年前。还有一个 9 位字节的不合时宜的野兽,祖先可以追溯到中世纪。 “优尼思”?不确定。如果你真的有兴趣,我可以查一下。干杯,
  • 好吧,我猜如果有人发明了某种方法来将 (2^32)-1 不同的值存储在少于 32 位中,那么很长一段时间内可能不会有 32 位。但是,在任何二进制平台上,只要数学有效,您将拥有 32 位。
  • @Alf:简洁明了。正确,是的,正如本文所示。但是,我建议您确实留下了很多步骤,并且在“C std 中这么说”响应中相当简短。我也没有看到联系,所以我可以理解他的困惑。

标签: c++ standards long-integer language-lawyer


【解决方案1】:

C++ 使用 C 标准中定义的限制(C++: 18.3.2 (c.limits), C: 5.2.4.2.1):

LONG_MIN -2147483647 // -(2^31 - 1)
LONG_MAX +2147483647 //   2^31 - 1

因此可以保证 long 至少为 32 位。

如果你想沿着漫长的迂回路线确定LONG_MIN/LONG_MAX 是否可以用long 表示,你必须查看 C++ 标准中的 18.3.1.2 (numeric.limits.members):

static constexpr T min() throw(); // Equivalent to CHAR_MIN, SHRT_MIN, FLT_MIN, DBL_MIN, etc.
static constexpr T max() throw(); // Equivalent to CHAR_MAX, SHRT_MAX, FLT_MAX, DBL_MAX, etc.

我将脚注移到了评论中,所以它与标准中出现的不完全一致。但它基本上暗示std::numeric_limits&lt;long&gt;::min()==LONG_MIN==(long)LONG_MINstd::numeric_limits&lt;long&gt;::max()==LONG_MAX==(long)LONG_MAX

因此,即使 C++ 标准没有指定(有符号)负数的按位表示,它也必须是二进制补码并且总共需要 32 位存储空间,或者它有一个明确的符号位,这意味着它也有 32 位的存储空间。

【讨论】:

  • 如果您通过所有 ad-hominem 攻击跟踪该帖子中令人难以置信的长评论链,这大致就是您所得到的。很高兴看到它可以简洁地解释而不叫任何人的名字。
  • 在 C++ 标准中的什么地方说 long 必须容纳值 [LONG_MIN, LONG_MAX]?我找不到任何此类参考。
  • @pst:请注意,限制允许大于这些值。符合要求的实现可以允许 -2^31,也可以允许 +2^31。
  • @John Dibling,C 和 C++ 标准之间有很多不同之处。 sizes of integer types 部分来自 C 标准。即使在 C++ 标准中,也有对 ISO C 标准的引用,由“另见:ISO C 子类 xxx”
  • @John,我编辑了我的评论,但 C++ 标准多次引用 ISO C 标准。 C++03 的附录 C 讨论了 C 和 C++ 标准之间的兼容性/不兼容性,它们没有提到两者在类型宽度上的任何差异。结合标准所说的 &lt;climits&gt;&lt;limits.h&gt; (S 18.2.2) 具有相同的内容,这表明 C 标准中声明的类型宽度也适用于 C++。
【解决方案2】:

答案是肯定的。阅读我的 OP 和所有 cmets 以了解确切原因,但这是简短版本。如果您对此有任何疑问或疑问,我鼓励您阅读整个线程和所有 cmets。否则接受这是真的:

  1. C++ 标准包括部分 C 标准,包括 LONG_MINLONG_MAX 的定义
  2. LONG_MIN 定义为不大于-2147483647
  3. LONG_MAX 定义为不小于+2147483647
  4. 在 C++ 中,整数类型以二进制形式存储在底层表示中
  5. 为了用二进制表示-2147483647+2147483647,您需要32 位。
  6. C++ long 保证能够表示LONG_MINLONG_MAX 的最小范围

因此,long 必须至少为 32 位1

编辑:

LONG_MINLONG_MAX 的值的大小由 C 标准 (ISO/IEC 9899:TC3) 第 5.2.4.2.1 节规定:

[...] 它们的实现定义的值应等于或大于所示的值 [...](绝对值),并带有相同的符号 [...]

— minimum value for an object of type long int
LONG_MIN -2147483647 // -(2 ^ 31 - 1)
— maximum value for an object of type long int
LONG_MAX +2147483647 // 2 ^ 31 - 1

132位:这并不代表sizeof (long) &gt;= 4,因为一个字节不一定是8位。根据标准,一个字节是一些未指定(平台定义)的位数。虽然大多数读者会觉得这很奇怪,但在实际硬件上,CHAR_BIT 是 16 或 32。

【讨论】:

  • 我被要求自己做出这个答案,因此当时间过去时我会接受这个
  • C 标准包括对这些值的最小量值的保证。 LONG_MAX 必须至少为 +2147483647,LONG_MIN 必须至多为 -2147483647。谷歌例如C standard minimum value of LONG_MAX如果你不相信我的话。
  • 您应该提到两个技术细节。首先,有符号范围是对称的(-2147483647 ... +2147483647 而不是 -214748364‌ 8 ... +2147483647)以允许有符号整数可能不使用二进制补码。最新的 C 和 C++ 标准仍然认为这是一种现实的可能性,即使最后一个商业非二进制补码机器在 1970 年代的某个时候停产(UNIVAC 系列之一,不确定是哪一个)。 (续)
  • 其次,更重要的是,long 至少有 32 个意味着sizeof(long) &gt;= 4。有CHAR_BIT 为16 或32 的真实机器,因此sizeof(long) 可能小到2 或1。与一个补码大型机和9 位迷你机不同,这些仍在生产中的AFAIK。 (它们大多是不寻常的微控制器。是的,与它们一起工作有点痛苦。)
  • @Zack:第二点,我在 OP 中确实说过,“此外,它是由实现定义的,一个字节中有多少位。我们大多数人可能习惯于处理 8 -bit 字节,但标准说一个字节中有 n 位。”但是我想这有点被埋没了,在答案中更明确地提及它会很有用。
【解决方案3】:

C++ 标准指出 &lt;climits&gt; 的内容与 C 标头 &lt;limits.h&gt; 相同(ISO C++03 文档中的 18.2.2)。

不幸的是,我没有 C++98(即 C90)之前存在的 C 标准的副本,但在 C99(第 5.2.4.2.1 节)中,&lt;limits.h&gt; 必须至少有这个最小值价值观。我认为这与 C90 没有什么不同,除了 C99 添加了long long 类型。

— minimum value for an object of type long int

LONG_MIN -2147483647 // −(2^31 − 1)

— maximum value for an object of type long int

LONG_MAX +2147483647 // 2^31 − 1

— maximum value for an object of type unsigned long int

ULONG_MAX 4294967295 // 2^32 − 1

— minimum value for an object of type long long int

LLONG_MIN -9223372036854775807 // −(2^63− 1)

【讨论】:

  • 我也没有 C 标准,(我是 C++ 人)。但是让我们假设您在此处发布的内容适用于 C++。我正在尝试连接 C 标准和 C++ 标准之间的点,并最终找出引用链,这些引用链毫不含糊地说 long 必须至少为 32 位。让我们简化一下,说 long 必须至少适应 LONG_MIN-LONG_MAX 的范围。
  • @John - 我认为这个讨论将在 MSN 的回答中比我的更多,所以我认为所有好的答案都会在那里。
【解决方案4】:

是的,C++ 标准明确规定未指定字节中的位数。也没有指定 long 中的位数。

为数字设置下限并不是指定它。

C++ 标准在一处说:

1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long).

实际上,在另一个地方,通过包含 C 标准:

CHAR_BITS >= 8; SHORT_BITS >= 16; INT_BITS >= 16; LONG_BITS >= 32

(除了 AFAIK,标识符 SHORT_BITS、INT_BITS 和 LONG_BITS 不存在,并且这些限制是由对类型最小值的要求推断出来的。)

这是因为在数学上需要一定数量的位来对 LONG_MIN..LONG_MAX 范围内的所有值进行编码(例如,对于 longs)。

最后,shorts、ints 和 longs 都必须由整数个字符组成; sizeof() 总是报告一个整数值。此外,逐个字符地遍历内存必须访问每一位,这带来了一些实际限制。

这些要求在任何方面都没有矛盾。任何满足要求的尺寸都可以。

很久以前就有机器的原生字长为 36 位。如果要将 C++ 编译器移植到它们,您可以合法地决定在 char 中使用 9 位,在 short 和 int 中使用 18 位,在 long 中使用 36 位。您还可以合法地决定在每种类型中使用 36 位,原因与今天在典型的 32 位系统上可以在 int 中使用 32 位的原因相同。存在使用 64 位字符的实际实现。

另请参阅C++ FAQ Lite 的第 26.1-6 和 29.5 节。

【讨论】:

  • 是的,但我的问题是一定要至少 32位,而不是完全 32位
  • 答案是“是的,'至少'”。在我的回答中,值是根据下限指定的,而不是确切的数量(sizeof(char) 除外,因为就 C++ 而言,char s 字节,但字节不是必须是八位字节)。因为这就是标准指定它们的方式。
【解决方案5】:

但是 Alf 和其他人明确指出 long 必须至少为 32 位。这是 我试图建立的。 C++ 标准是明确的,数字 未指定字节中的位数。 可能是 4, 8, 16, 42... 那么如何 从能够 容纳数字 LONG_MIN-LONG_MAX 至少为 32 位?

为了获得至少那么多位模式,您需要在值表示中使用 32 位。由于 C++ 需要整数的二进制表示(标准中的显式语言,第 3.9.1/7 节),Q.E.D.

【讨论】:

  • 为什么你说需要那么多位模式?在编写“Q.E.D.”之前,您必须添加很多步骤
  • @MooingDuck:不,普通算术没有中间步骤。问题是“如何建立连接”,它是这样的:2^n = M 直接给出 n = log2(M)。看,没有中间步骤。好吧,除非你想在没有 log2 按钮的计算器上计算它。那么 log2(M) = ln(M)/ln(2)。 :-)
猜你喜欢
  • 2014-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-13
  • 2011-11-08
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多