【问题标题】:Cross-platform: selecting data types to use 32/64 bit跨平台:选择数据类型以使用 32/64 位
【发布时间】:2009-10-16 09:52:17
【问题描述】:

我正在试验我的第一个跨平台应用程序,它需要在 Linux Redhat 5.3 和 Windows XP/Vista/7 上运行。

由于某些操作系统将运行 x86 或 64,我想知道要声明哪些数据类型。

我不想使用任何库来实现跨平台可移植性;我想先自己试验一下。

如果我需要一个 int,我应该声明 int32 或 int64 还是只声明 int?

如果我要在 64 位操作系统上编译并使用 int32,那么数据是否会被截断为 32 位值,这样我会丢失一些数据?

我想知道如果我在具有不同架构的不同操作系统上运行,我应该如何声明。

【问题讨论】:

    标签: c


    【解决方案1】:

    在许多 64 位操作系统(如 64 位 Linux)中,int 仍然只有 32 位宽;只有 long 和指针是 64 位宽的。这称为LP64 data model。这样做的原因是,在许多情况下,int 不需要比 32 位提供的范围更大,使用 64 位只会浪费内存。在 64 位 Windows 下,evens longs 是 32 位的(为了兼容 32 位 Windows),只有 long long 是 64 位的;这称为 LLP64 数据模型。

    如果您的应用程序要在 32 位和 64 位操作系统上运行,那么 32 位整数的范围显然就足够了 -- 否则,您将在 32 位上遇到麻烦操作系统。所以在这些情况下继续使用整数。如果您可以确定需要 64 位整数范围的情况,请显式使用 int64_t(在 stdint.h 中定义)。为确保写入磁盘的二进制数据格式跨平台兼容,请在这些地方明确使用 int32_tint64_t...但也要注意潜在的字节顺序问题。

    最后,在编写 64 位代码时,请注意在 LP64 数据模型中指针无法转换为整数,因此请改用 uintptr_t

    如果您的代码干净整洁,那么 32 位/64 位可移植性应该几乎不成问题——您需要了解的内容并不比我上面写的要多。 Windows 和 Linux 之间的可移植性将产生比 32 位和 64 位之间的可移植性更大的问题。

    【讨论】:

    • +1,很好的解释。但请注意,Windows 不使用 LP64 模型(它使用 LLP64)。只要您的代码不假设 long 的大小(或者如果您不使用它们),这不会影响您。
    • 好点——我已经编辑了答案以添加此信息。
    【解决方案2】:

    如果您需要整数,请输入int,依此类推。如果您需要对数据类型可以保存什么做出假设(例如,您要求它具有 32 位),请查看stdint.h

    只要您确保不对数据类型可以容纳的内容做出假设,您就会处于良好状态。当您执行诸如假设数据类型将保留 n 位之类的操作时,您就进入了实现定义的领域,您需要确保它在两个平台上都能正常工作。

    【讨论】:

      【解决方案3】:

      在大多数情况下,您不需要 固定 大小 - 您只需要 最小 大小。普通的旧 C 数据类型确实具有这样的最小大小(范围):

      type               | minimum size
      -------------------+---------------------------------------------
      char               | at least 8 bits (but see below)
      signed char        | -127 to 127
      unsigned char      | 0 to 255
      short              | -32767 to 32767
      unsigned short     | 0 to 65536
      int                | -32767 to 32767
      unsigned int       | 0 to 65536
      long               | -2147483647 to 2147483647
      unsigned long      | 0 to 4294967295
      long long          | -9223372036854775807 to 9223372036854775807 (see below)
      unsigned long long | 0 to 18446744073709551615 (see below)
      

      (char 必须与 signed charunsigned char 具有相同的范围。long longunsigned long long 是 C99 规范的新内容,但在许多仅支持旧标准的编译器中作为扩展存在)。

      使用足够大的大小以适合您感兴趣的值范围,加上size_t 用于对象大小/对象数量/数组索引,在大多数情况下您会是对的。

      <stdint.h> 中的附加类型值可能很有用,但应谨慎使用。

      【讨论】:

      • 请注意,long long 是 C99 的新成员,尽管它可能会在任何体面的编译器中实现。
      【解决方案4】:

      您需要使用适合您正在处理的数据的数据类型,并且要确保不会跨平台更改,请使用 stdint.h 中的 uint32_t、uint16_t 等

      最重要的是,如果您正在操作一个大小随底层架构而变化的值,例如容器的大小,你应该使用 size_t 因为它会适应编译器目标,例如32 位或 64 位。

      【讨论】:

        猜你喜欢
        • 2016-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多