【问题标题】:Size of int, short, long, long long?int、short、long、long long 的大小?
【发布时间】:2019-12-12 19:06:25
【问题描述】:

根据 C99 §5.2.4.2.1-1,以下类型的大小取决于实现。据说它们的大小等于或大于这些值:

short           >= 8 bits
int             >= 16 bits
long            >= 32 bits
long long       >= 64 bits

我一直听说long 总是32-bits,并且它严格等同于看起来不对的int32_t

什么是真的?

【问题讨论】:

标签: c types c99


【解决方案1】:

在我的计算机上,Linux 中的 long 是 64 位。

Windows 是唯一在 64 位模式下使用 32 位 long 的主要平台,这正是因为现有代码中普遍存在错误假设。这使得在 Windows 上更改 long 的大小变得很困难,因此在 64 位 x86 处理器上,long 在 Windows 中仍然是 32 位,以保持各种现有代码和定义兼容。

【讨论】:

  • 非常感谢。
  • 68000 的 C 实现能够容纳预期 int 为 16 位的代码以及预期为 32 位的代码。如果函数的原型是使用shortlong 而不是int,则使用一种设置编译的代码可以调用使用另一种设置编译的函数,并且库调用可以根据需要调用该库的两个版本之一。唯一的主要问题是调用非原型或可变参数函数。我不认为期望基于八位字节的机器的编译器将继续支持 32 位 long 是不合理的。
【解决方案2】:

根据定义,该标准是正确的,您解释它的方式也是正确的。某些类型的尺寸可能会有所不同。该标准仅规定了这些类型的最小宽度。通常(但不一定)int 类型与目标处理器具有相同的宽度。

这可以追溯到过去,性能是一个非常重要的方面。每当您使用 int 时,编译器都可以选择仍然保持至少 16 位的最快类型。

当然,今天这种方法不是很好。这只是我们必须忍受的东西。是的,它可以破坏代码。因此,如果您想编写完全可移植的代码,请使用 stdint.h 中定义的类型,例如 int32_t 等。或者至少,如果您希望变量包含不在[−32,767; 32,767] 范围内的数字,则永远不要使用int

【讨论】:

  • 严格来说,INT_MIN 只能保证至少是-32767
  • 虽然严格来说,INT_MIN 在您可以使用 GCC、Clang、TCC 或 MSVC 定位的任何平台上都保证为 <= -32768...
  • @AnttiHaapala:让我们定义一百万个标准;其中一个是“ISO/IEC 9899:2011”,一个是“GNU 标准 C”(其中 INT_MIN 是 long 始终是 32 位和它严格等同于int32_t)。
  • @SteveSummit C 有一个意图:-o?说真的,我也明白这一点,但这肯定是在没有太多意识到这可能导致的问题的时候设计的。能够在 14 位微控制器和 32 位服务器上使用 int 的可移植性与尝试在 32 位和 64 位台式 PC 上编译相同代码时所需的可移植性大不相同 - 后者肯定是阻碍规范中的这种模糊性。可以说它实现了语言的可移植性,但没有代码...的可移植性
  • @Marco13 我不得不承认,这是一组复杂且有争议的问题。 <stdint.h> 无疑是一个重要的工具。但是(也许我很固执)我仍然认为说“普通的int 是不可移植的,永远不应该使用”是错误的。
【解决方案3】:

我一直听说long 总是 32 位的,它严格等同于看起来不对的 int32_t

我很好奇你是从哪里听到的。这绝对是错误的。

有很多系统(我认为主要是 16 位或 32 位系统或 64 位 Windows)long 是 32 位,但也有很多系统 long 是 64 位.

(即使long是32位,它也可能与int32_t不是同一类型。例如,如果intlong都是32位,它们仍然是不同的类型,并且int32_t 可能被定义为其中之一。)

$ cat c.c
#include <stdio.h>
#include <limits.h>
int main(void) {
    printf("long is %zu bits\n", sizeof (long) * CHAR_BIT);
}
$ gcc -m32 c.c -o c && ./c
long is 32 bits
$ gcc -m64 c.c -o c && ./c
long is 64 bits
$ 

整数类型的大小要求几乎如您在问题中所述(short 的大小错误)。该标准实际上根据范围而不是大小来说明其要求,但是与二进制表示的要求一起意味着以位为单位的最小大小。要求是:

  • charunsigned charsigned char:8 位
  • shortunsigned short:16 位
  • intunsigned int:16 位
  • longunsigned long:32 位
  • long longunsigned long long:64 位

每个有符号类型都有一个范围,其中包括列表中前一个类型的范围。没有上限。

intlong 分别为 32 位和 64 位是很常见的,尤其是在非 Windows 64 位系统上。 (POSIX 要求 int 至少为 32 位。)long long 在我见过的每个系统上都是 64 位,尽管它可以更宽。

【讨论】:

  • 在标准出现之前,人们普遍认为char是至少8位的最小可寻址单元,short是至少16位的最小实用类型,@987654349 @ 是至少 16 位的最实用的类型,long 是至少 32 位的最实用的类型。在任何类似于典型微型计算机的东西上,这意味着大小分别为 8、16、16 或 32 位和 32 位,我不认为标准的作者打算不期望典型的微型计算机使用这些大小。
  • @supercat:我正在使用 64 位 long 的系统上输入此内容。你真的认为标准的作者会对此有疑问吗?或者你对“典型的微型计算机”有什么奇怪的意思? (请注意,标准和我回答的问题都没有提到微型计算机。)
  • 我认为至少该标准的一些作者会对无法容纳期望 32 位 long 的代码的设计感到失望。 68000 的编译器通常可以配置为使用 16 位或 32 位 int,并且支持 32 位和 64 位 long 之间的类似选择应该更容易,因为缺少整数提升问题调用可变参数函数时。即使在 64 位机器上,在 32 位范围足够的情况下,使用 32 位值的数组通常也比使用 64 位值更快。
  • 在经典的 Macintosh 上,使用一个 int 设置编写的代码可以与使用另一个设置的代码互操作,前提是所有函数都已正确原型化,没有使用可变参数函数或 va_list,并且没有人试图通过使用类型int 的任何标准库函数的地址。与 68000 不同,x64 可以以与 32 位相同的成本传递 64 位参数,因此对于“32 位有符号作为 64 位和符号扩展填充传递”的特殊编译器类型应该有什么困难? “32 位无符号作为 64 位以零填充传递”...
  • 是的,其他人标记了它,并且在问题的上下文中阅读此内容以及您的编辑,我将看看我是否可以撤回它。
【解决方案4】:

请注意,标准没有为intshortlong 等类型指定大小,而是最小范围的值 这些类型必须能够表示。

例如,int 必须能够至少表示[-32767..32767]1 范围,这意味着它必须至少 > 16 位宽。它可能更宽,原因有两个:

  • 平台提供了更多值位来存储更广泛的范围(例如,x86 使用 32 位存储整数值,使用 64 位存储长整数);

  • 平台使用填充位来存储部分值以外的内容。

作为后者的一个例子,假设您有一个 9 位平台和 18 位字。在 18 位字的情况下,其中两个位是填充位,用于存储部分值 - 该类型仍然只能存储 [-32767..32767],即使它比16 位。

&lt;stdint.h&gt; 标头确实定义了具有特定固定大小(16 位、32 位)的整数类型,但它们可能并非无处不在。


  1. C 不要求有符号整数使用 2 的补码表示,这就是为什么范围不是从 [-32768..32767] 开始的原因。

【讨论】:

    猜你喜欢
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    相关资源
    最近更新 更多