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”。在此列表中,每种类型提供的存储空间至少与列表中它前面的类型一样多。普通整数具有执行环境架构所建议的自然大小

此外,char3.9.1/ 的大小描述为:

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

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

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

这使我得出以下结论:

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

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


这篇文章中,Alf P. Steinbach 说:

long 保证(至少)32位。

这违背了我所理解的根据标准在 C++ 中的基本类型的大小。通常我会认为这是一个初学者的错误,但由于这是 Alf,我认为值得进一步调查。

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

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

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

所以无论 along有多大,它都必须足够大,才能将 LONG_MIN 保持到 LONG_MAX。

但是 Alf 和其他人特别指出 long 必须至少为 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) 定义<climits>为:

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

5 回答 5

37

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可以由 a 表示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<long>::min()==LONG_MIN==(long)LONG_MINstd::numeric_limits<long>::max()==LONG_MAX==(long)LONG_MAX

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

于 2010-12-01T22:32:09.360 回答
17

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

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

因此 along必须至少为 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

1 32 位:这并不意味着sizeof (long) >= 4,因为一个字节不一定是 8 位。根据标准,一个字节是一些未指定(平台定义)的位数。虽然大多数读者会觉得这很奇怪,但真正的硬件CHAR_BIT是 16 或 32。

于 2010-12-02T16:51:22.363 回答
7

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

您需要在值表示中使用 32 位才能获得至少那么多位模式。由于 C++ 需要整数的二进制表示(标准中的显式语言,§3.9.1/7),QED

于 2010-12-01T23:22:35.157 回答
7

C++ 标准指出其内容<climits>与 C 标头<limits.h>(ISO C++03 文档中的 18.2.2)相同。

不幸的是,我没有 C++98(即 C90)之前存在的 C 标准的副本,但在 C99(第 5.2.4.2.1 节)中,<limits.h>必须至少具有这个最小值。我不认为这从 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)
于 2010-12-01T22:35:42.777 回答
7

是的,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 节。

于 2010-12-01T23:52:39.503 回答