【问题标题】:What's the difference between unsigned long/long/int in c/c++?c/c++ 中的 unsigned long/long/int 有什么区别?
【发布时间】:2010-03-31 03:37:28
【问题描述】:

它们似乎都占用了 4 个字节的空间,

那有什么区别呢?

【问题讨论】:

    标签: c syntax integer long-integer


    【解决方案1】:

    首先,int/long 的大小是未指定的。所以在你的编译器上,intlong 可能是相同的,但这在编译器中并不通用。

    至于unsigned longlong的区别:

    假设 4 个字节,long 的范围为 -2,147,483,6482,147,483,647。无符号长整数的范围为 04,294,967,295

    另一个区别是溢出。对于有符号类型,溢出具有未指定的行为。但是对于无符号类型,溢出肯定会“环绕”。

    【讨论】:

    • 环绕作为溢出算术处理。当您在无符号长整数中点击(在 rlbond 的示例中)4294967296 时,加 1 将“环绕”,它将成为最小值:0。加 2 将环绕并使其变为 1,等等。
    • 似乎这种东西也可以用于签名类型,对吧?
    • 可以,但正如 rlbond 所说,当您溢出有符号类型时,行为是未定义的。无符号类型保证正确包装;签名类型没有这样的保证,并且行为可能会从一个平台更改为下一个平台。
    • 4,294,967,296 在答案和@Dan 的评论中都应该是4,294,967,295
    • 我想我应该说“假设四个 8 位字节”。
    【解决方案2】:

    C 语言规范允许 int 和 long 类型的实现在几个限制内从一个平台到另一个平台有所不同。这种可变性对于跨平台代码来说是一个令人头疼的问题,但它也是一种资产,因为它使知情的程序员能够在本机处理器速度和硬件架构上的完整数值范围之间平衡他们的设计目标,而硬件架构不能同时提供这两者。

    一般来说,“int”应该映射目标 CPU 架构机器的机器寄存器大小,因此加载、存储和操作 int 类型数据应该直接转换为使用目标处理器的本机寄存器的操作。

    为了节省内存空间,Int 可以小于机器寄存器大小(大整数占用的 RAM 是小整数的两倍)。即使在 64 位架构上,也很常见将 int 视为 32 位实体,其中与旧系统的兼容性和内存效率是高优先级。

    “long”的大小可以与“int”相同或更大,具体取决于目标体系结构的寄存器大小。如果目标架构不支持其本机机器寄存器中的大值,则可以在软件中实现对“long”的操作。

    如今,您可以在其中发现 int 和 long 之间的区别,专为提高电源效率或嵌入式设备而设计的 CPU 芯片。用于台式机或笔记本电脑等通用 CPU 的编译器通常将 int 和 long 视为相同的大小,因为 CPU 有效地使用 32 位寄存器。在手机等较小的设备上,CPU 可以更自然地处理 16 位数据,并且必须努力处理 32 位或更大的数据。

    每个寄存器更少的位意味着芯片上需要更少的电路,更少的数据线将数据移入和移出芯片,更低的功耗和更小的芯片裸片尺寸,所有这些都可以降低成本(以美元和瓦)设备。

    在这样的架构中,您很可能会发现 int 的大小为 16 位,而 long 的大小为 32 位。也可能存在与使用 long 相关的性能损失,这是由于等待状态以通过 16 位数据总线在多次读取中加载 32 位造成的,或者是由于在软件中实现长操作(加法、减法等)造成的,如果本机hardware 不支持硬件中的此类操作。

    作为一般规则,关于 int 和 long 的唯一假设是 int 的范围在任何架构上都应始终小于或等于 long。您还应该假设有一天您的代码将针对不同的架构重新编译,您当前在 int 和 long 之间看到的任何关系都不再存在。

    这就是为什么即使在日常的普通编码中,您也应该小心地将 int 与 long 分开。它们今天可能完全兼容分配,因为它们在您当前的硬件平台上的实现细节是一致的,但不能保证在所有平台上都是一致的。

    【讨论】:

      【解决方案3】:

      嗯,unsigned longlong 之间的区别很简单——上限。签名long 从(在平均 32 位系统上)大约 -21 亿 (-2^31) 到 +21 亿 (+2^31 - 1),而 unsigned long 从 0 到 42 亿 (2 ^32 - 1)。

      碰巧在许多编译器和操作系统(显然包括您的)上,int 也是一个 32 位值。但是 C++ 标准没有确定任何这些类型的最大宽度,只有 最小 宽度。在某些系统上,int 是 16 位。在某些系统上,long 是 64 位。很大程度上取决于目标处理器架构,以及它的基本字长。

      limits.h的存在是为了定义当前编译环境下各种类型的最大容量,stdint.h的存在是为了提供与环境无关的类型保证宽度,如int32_t

      【讨论】:

      • 无论是什么系统,intlong 都具有相同的长度——基本字长。对吗?
      • 不,一点也不。在较旧的 16 位编译器上,int 通常是 2 个字节,而 long 是 4 个字节。关于尺寸,这里没有硬性规定,只有相对的规定。 char 将始终小于或等于 short,short 将始终小于或等于 int,int 将始终小于或等于 long。不过,从技术上讲,您可以遵守 C++ 标准并将它们全部四个都设为一个字节。
      • 使用 limits.h 或 stdint.h 来帮助您。如果您知道需要 32 位值,请使用 stdint.h 中的 int32_t 而不是 int 或 long。这样,无论您将代码移植到何处,它都将始终为 32 位。
      • 标准 C 要求 int 至少为 16 位,long 至少为 32 位。然而,现在有 stdint.h,它定义了诸如 int_fast16_t 之类的类型 = 至少 16 位(但可能更多)的有符号整数类型,并且在目标平台上“快速”(例如,在现代计算机上它通常可能是 32 位) )。如果您对尺寸有特殊要求,则应使用这些类型。参见例如 stdint.h 和 limits.h维基百科。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-10
      • 2022-01-21
      • 2023-03-14
      • 2022-12-20
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多