我可以假设 long int 的大小总是 4 个字节吗?

Posted

技术标签:

【中文标题】我可以假设 long int 的大小总是 4 个字节吗?【英文标题】:Can I assume the size of long int is always 4 bytes? 【发布时间】:2016-06-21 01:16:36 【问题描述】:

long int(据我所知是long 的同义词)总是4 字节吗?

我可以依赖它吗?如果不是,那么对于基于 POSIX 的操作系统来说是不是真的?

【问题讨论】:

只是提醒大家sizeof 考虑了填充和对齐。具有 8 个字节的 sizeof(unsigned long) 是符合标准的,但溢出的行为类似于 4 个字节。尝试使用sizeofCHAR_BITS 来计算整数类型的限制是错误的。在应该使用的时候使用limits.h 你真的应该阅读(先删节,然后是完整版)C-faq,它起源于 Usenet,当时它是人们的地方一个主题的知识聚集在同一个地方(现在,它在几个站点中很普遍......),因此它导致了令人难以置信的详尽和出色的常见问题解答。见c-faq.com/versions.html。阅读它可以让您大开眼界,了解更多您可能甚至不知道您需要了解的问题(第 5 节 - 空指针 - 包含常见问题解答,我很震惊(并且很感激)发现) 不,我的电脑上是 8 Range of values in C Int and Long 32 - 64 bits的可能重复 在大多数 64 位系统(例如 x86-64 Linux 和 OS X)上是 8。 Windows 是主要的例外,因为为 32 位 Windows 编写的大量代码都是为 32 位 Windows 编写的,几乎没有努力编写没有假设的可移植代码。同样出于 ABI 的原因:我认为某些结构的定义中有 longs,但它们不需要是 64 位的。因此,MS 决定将 long 设为 32 位,以保持其 ABI 和现有代码库中的结构大小相同。 【参考方案1】:

除了char 之外,标准没有说明任何整数类型的确切大小。通常,long 在 32 位系统上为 32 位,在 64 位系统上为 64 位。

然而,该标准确实指定了 最小 大小。来自C Standard 的第 5.2.4.2.1 节:

1 下面给出的值应替换为常量表达式 适用于#if 预处理指令。而且, 除CHAR_BITMB_LEN_MAX 外,以下应为 替换为具有相同类型的表达式 被转换的相应类型的对象的表达式 根据整数促销。 他们的实现定义 值的大小(绝对值)应等于或大于 显示的那些,带有相同的标志。

...

long int 类型对象的最小值

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

long int 类型对象的最大值

LONG_MAX +2147483647 // 2^31−1

这表示long int 必须至少为 32 位,但可能更大。在CHAR_BIT 为 8 的机器上,这给出了 4 的最小字节大小。 CHAR_BIT 等于 16,long int 可以是 2 个字节长。

这是一个真实的例子。对于以下代码:

#include <stdio.h>

int main ()

    printf("sizeof(long) = %zu\n", sizeof(long));
    return 0;

Debian 7 i686 上的输出:

sizeof(long) = 4

CentOS 7 x64 上的输出:

sizeof(long) = 8

所以不,您不能对大小做出任何假设。如果需要特定大小的类型,可以使用stdint.h 中定义的类型。它定义了以下类型:

int8_t: 签名 8 位 uint8_t: 无符号 8 位 int16_t:带符号的 16 位 uint16_t:无符号 16 位 int32_t:签名 32 位 uint32_t:无符号 32 位 int64_t:签名 64 位 uint64_t:无符号 64 位

stdint.h 标头在标准的第 7.20 节中进行了描述,确切的宽度类型在第 7.20.1.1 节中进行了描述。标准规定这些 typedef 是可选的,但它们存在于大多数实现中。

【讨论】:

但是这些类型定义在标准中!只是实现定义了它们是否实际存在以及它们代表哪些类型! @nouney 不要混淆最小位数和最小字节数。我不记得任何禁止1 == sizeof(char) == sizeof(int) 的东西。您能否提供标准中的具体引用,即 "int is at least 2 bytes" @nouney char 可以大于 8 位。当然,如果它是 32 位(当然还是 sizeof 1),处理 8 位文本编码之类的数据会很痛苦,但通常这样的平台不用于文本处理。 我不会说long 通常是 64 位的,因为它不在 Windows 上,而且 Windows 被广泛使用。当然,标准本身并没有定义这一点,因此两种实现都符合标准,但最终结果是大量的 unix C(和 C++)代码截断 Windows 上的 64 位指针(只需停止将指针存储在整数中) ,该死的!:D)。当然,这从根本上是由于使用 按标准 具有 [−2147483647, +2147483647] 范围的类型来存储大于该范围的值,这有点荒谬,但是哦,好吧 :) 我一直都知道 sizeof(char) 【参考方案2】:

使用代码sizeof(long int) 并检查尺寸。它将为您提供当前正在工作的系统上 long int 的大小(以字节为单位)。特别是您的问题的答案是否定的。在 C 或 POSIX 或任何地方都无法保证。

【讨论】:

IMO,这没有回答问题。 它实际上帮助了我:) @nouney 如何声明 C 标准没有确切的大小保证,或者 POSIX 标准不能回答这个问题?这不是最好的答案,但肯定不会错。 @Leliel 因为当我发表评论时,anwser 只是“使用 sizeof”。 sizeof(long int) 将填充和对齐限制因素纳入其结果。 sizeof 返回“16”是完全有效的,即使你只被允许使用其中的四个字节。【参考方案3】:

不,C 标准和 POSIX 都不保证这一点,事实上 most Unix-like 64-bit platforms 有一个 64 位(8 字节)long

【讨论】:

大多数 32 位及以上平台上的 Int 都是 32 位的(无论如何,AFAIK),拥有与 int 大小相同的 long 有什么意义?在我的系统(英特尔、64 位 Linux、gcc)上,int 为 32,long 为 64。 @jamesqf:在 1980 年到 2005 年间发布的绝大多数平台上,short 是 16 位,long 是 32 位,“int”是 16 位或 32 位,以方便实现。在 C99 添加 stdint.h 之前为 16 位和 32 位类型提供固定大小的类型很有帮助。但是,作为后者的一个很好的附加复杂因素,在具有 32 位“int”的系统上,int32_t 可能与“int”或“long”兼容,但不允许符合的实现使其与两者兼容。 【参考方案4】:

正如@delnan 所指出的,POSIX 实现将longint 的大小保持为未指定,并且它通常在32 位和64 位系统之间有所不同。

long 的长度主要与硬件相关(通常与 CPU 上数据寄存器的大小相匹配,有时还与其他与软件相关的问题,如操作系统设计和 ABI 接口)。

为了让您放心,sizeof 不是一个函数,而是一个编译器指令*,因此您的代码在使用 sizeof 时不使用操作 - 这与写一个数字相同,只是它是可移植的。

使用:

sizeof(long int)

* 正如 Dave 在 cmets 中指出的,sizeof 将在编译期间无法计算值时在运行时计算,例如使用可变长度数组时。

另外,正如另一条评论中所指出的,sizeof 考虑了实现使用的填充和对齐,这意味着实际使用的字节可能与内存中的大小不同(这在位移时可能很重要)。

如果您正在寻找特定字节大小的变量,请考虑使用字节数组或(我认为受支持)C99 在stdint.h 中定义的类型 - 正如@dbush 所建议的那样。

【讨论】:

不是(只是)硬件。您可以在 64 位硬件上运行 32 位 Linux,甚至可以使用 x32 ABI,其中数据类型的大小与 32 位硬件相同,但硬件实际上运行在 64 位模式下。 @delnan ,是的,这是真的。我可能应该通过将 usually 更改为 mostly 并在括号中添加信息来澄清这一点。 @delnan ,我并不是要跳过你的答案,我只是认为最好澄清sizeof 是一个编译器指令,以消除任何人可能有猜测的任何感知原因在大小。 小修正:sizeof 在运行时计算,当(如果)您在 C99 或更高版本中使用可变长度数组或可变修改类型(或 'gnu89' 作为 GCC 扩展)但大多数代码不这样做。【参考方案5】:

编译器根据硬件和操作系统的类型确定大小。

因此,不应对尺寸做出假设。

【讨论】:

【参考方案6】:

当我们第一次在 ICL Series 39 硬件上实现 C 时,我们采用标准字眼并将数据类型映射到该机器架构上的自然表示,即 short = 32 位,int = 64 位, long = 128 位。

但我们发现没有任何严肃的 C 应用程序可以工作;他们都假设映射short = 16、int = 32、long = 64,我们不得不改变编译器来支持它。

所以不管官方标准怎么说,多年来每个人都集中在long = 64 位,而且不太可能改变。

【讨论】:

真的吗?至少在 GCC/Glibc/GNU/Linux 上,平台似乎在 int = 32、long long = 64、long = 本机字长(32 或 64)上收敛,当然不会在 long = 64 上收敛。在不完全是小众架构的 x86 上,long 是 32 位的。 OSX、Solaris、z/OS、SysV 是其他一些遵循此约定的操作系统。 对于比 OSX、Linux、z/OS 或 SysV 使用更广泛的系统,有 Windows,它有另一个不同于你的约定(总是 64)或那些(总是与一个指针),即始终为 32 位。 恕我直言,正确的补救措施是有一个标准的方法,代码可以指定在某些上下文中需要什么样的“int”、“long”等[通常是每个文件,这样将函数声明为接受“int”的头文件将始终具有相同的含义]。让 64 位系统模拟 16 位或 32 位“int”应该相当简单,并且考虑到 C 中所有奇怪的细微差别(例如在 64 -bit 系统,uint32_t 模乘不适用于所有值)。 大多数用于 x86_16、x86_32、32 位 ARM、AVR、PIC 和 8051 的编译器对 long 使用 32 位整数,其中一半对 int 使用 16 位整数。但我认为sizeof(short)*CHAR_BIT==16 可能是真的。【参考方案7】:

standard 没有说明long int 的大小,因此它取决于您使用的环境。

要在您的环境中获取long int 的大小,您可以使用sizeof 运算符并获取long int 的大小。类似的东西

sizeof(long int)

C 标准对类型的大小只要求以下几点

int >= 16 位, 长 >= 32 位, long long(C99 起)>= 64 位 sizeof(char) sizeof(char) == 1 CHAR_BIT >= 8

剩下的是定义的实现,所以如果 有人遇到了一些 int 有 18/24/36/60 位的系统,一个 补码形式,sizeof(char) == sizeof(short) == sizeof(int) == sizeof(long) == 4、48 位长或 9 位字符,例如标准委员会关心的 Exotic 架构和列表 C 标准支持的平台

上面关于 long int 的观点是完全错误的。大多数 Linux/Unix 实现将 long 定义为 64 位类型,但它只有 32 位 Windows,因为它们使用不同的数据模型(看看 表在这里64-bit computing),这与 32 位或 64 位无关 操作系统版本。

Source

【讨论】:

【参考方案8】:

来自Usrmisc's Blog:

标准完全由编译器决定,这也意味着相同的编译器可以使其依赖于选项和目标架构。

所以你不能

顺便说一句,即使long int 也可能与long 相同。

【讨论】:

这个答案有什么问题?为什么有人给她负分?毕竟,它是问题的答案,并且与其他答案相比,它的简单性与众不同,这对于一些正在寻找答案的人来说可能很重要。不是吗?【参考方案9】:

简短的回答:不!您不能对long int 的大小做出固定的假设。因为,标准(C 标准或 POSIX)没有记录 long int 的大小(如反复强调的那样)。只是为了提供一个反例来证明您的看法,大多数 64 位系统的 long 大小为 64!为了最大限度地提高便携性,请适当地使用sizeof

使用sizeof(long int)检查大小,它返回long的大小,以字节为单位。该值取决于系统或环境;意思是,编译器根据硬件和操作系统确定大小。

【讨论】:

【参考方案10】:

不,您不能假设因为“长”数据类型的大小因编译器而异。 查看this文章了解更多详情。

【讨论】:

以上是关于我可以假设 long int 的大小总是 4 个字节吗?的主要内容,如果未能解决你的问题,请参考以下文章

64位机器中的C++ int vs long long

C语言中long转换成int是将低位给int吗

转载各种数据类型占用内存大小,以及字字节位

如果平台上“long”和“int”的大小相同 - “long”和“int”有啥不同吗?

C++ 标准规定 int、long 类型的大小是多少?

使用非固定整数(int、long)而不是固定大小的整数(int64_t、int32_t)有啥好处吗?