【问题标题】:Detect 64-bits in C using size_t使用 size_t 检测 C 中的 64 位
【发布时间】:2013-06-08 09:39:01
【问题描述】:

sizeof(size_t)==8 是否相当于说平台是 64 位的? 反过来说sizeof(size_t)==4是不是相当于说平台是32位的?

更重要的是,该测试是否在所有情况下都安全可靠,同时牢记操作系统和编译器的可移植性?是否有一些奇怪的极端情况,包括size_t 可能丢失的潜在情况?

我有点担心size_t 可能只适用于 C99 环境。

【问题讨论】:

  • “平台是 32/64 位”的概念定义不明确。这是什么意思?这可能意味着int 中的任何一个都这么宽,long 这么宽,CPU 的指令带有这么宽的操作数,操作系统供应商在产品名称中有数字,等等。您要解决的实际问题是什么?为什么你认为“平台大小”是一个问题? sizeof(size_t) 可以是 1(!),它可以是 32 位或 64 位或其他平台。整数类型的限制在<limits.h>,其他的都在猜测。

标签: c 64-bit portability


【解决方案1】:

实际上,是的,这是安全可靠的。您将来可能瞄准或曾经瞄准的平台都是字节可寻址的,具有 8 位字节,size_t 等于机器字长。大多数平台都保证这种情况会无限期地持续下去(例如,POSIX 就保证了这一点)。

从理论上讲,不,这并不安全可靠。 Cray-1、PDP-10 和各种 DSP 系统等不起眼的系统会让您大吃一惊。但是,请考虑一下:您为 Cray-1 设计软件的可能性有多大,在您旁边的初级工程师出生之前就已经过时了?

【讨论】:

  • 没有提到 Univac,但是我经常收到一些系统的请求,这些系统多年来已不再销售,但仍支持一些晦涩且有弹性的业务。最小的共同点似乎是 C89 编译器的可用性。
【解决方案2】:

size_t 是一种能够表示任何对象大小的数据类型。

64 位 通常指的是 64 位可用于寻址虚拟内存。在 C 中,内存是使用指针寻址的。因此,sizeof(void*) 似乎更适合测试 64 位环境。

但是,C 标准不保证这一点。可能存在不存在使用 C 确定硬件架构的安全可靠方法的模糊情况。

因为sizeof 返回的大小是char 大小的倍数,您可能需要查看CHAR_BIT(在limits.h 中定义)以查看其中有多少位在一个字符中。

【讨论】:

  • 没想到这一点,但你是对的,sizeof(void*) 看起来是一种更简洁的方式来检查 64 位/32 位。
【解决方案3】:

更重要的是,考虑到操作系统和编译器的可移植性,这个测试在所有情况下都安全可靠吗?

没有“可移植的方式”来做到这一点,因为C标准让环境定义SIZE_MAX任意大(只要大于65535)。但是C标准也没有定义什么是“32位”和“64位”平台。

但是,在常见的内存模型上,size_t 在 32 位平台上是 32 位,在 64 位平台上是 64 位。

我有点担心size_t 可能只适用于 C99 环境。

size_t 也在 C89 中。所以,只要你的环境是标准的,就应该定义size_t

【讨论】:

  • 嘿嘿,C89对码字用户的要求最低。这是个好消息。
【解决方案4】:

这里真正的问题是:如果sizeof(size_t) == 8sizeof(size_t) == 4 都不为真,你会怎么做。您也可以确保检查CHAR_BIT == 8 - 如果平台不是“常见的现代硬件”,这可以避免混淆,例如Cray-1,PDP-10 在别处提到。

在未来的某个时候,我预测 128 位机器将会存在,但我也猜想这还很遥远,因为我们目前只能使用 64 位中 75% 的可用位内存地址的机器(size_t 与内存寻址有关)。请注意,高 16 位为我们提供的内存是当前限制的 65535 倍,因此在内存空间用完之前还有很长的路要走。 [不要介意当前构建具有 256TB 内存的机器的成本,这是当前的限制——大多数系统甚至都没有接近 DISKSPACE 中的成本,更不用说 RAM(在我的脑海中粗略计算,但 42 位是 4TB,所以我认为 48 位应该是 32 倍)]。

【讨论】:

    【解决方案5】:

    CHAR_BIT 已经被提及,并且理论上存在size_t 内的额外填充不用于该值的情况。但是,您可以在运行时安全且可移植地计算 unsigned 整数类型的相关值位的确切数量。

    size_t s;
    int    num_of_bits;
    
    for (s=1, num_of_bits=0; s!=0; s<<=1, num_of_bits++);
    

    如果您在编译时需要此信息,最好将#define SIZEOF_BITS 32 设置为特定于平台的值,并在您的单元测试中验证它是否满足实际的 num_of_bits。你确实有单元测试,对吧?

    【讨论】:

      【解决方案6】:

      要检查指针,这是真的,但不是在运行时!假设您正在分发源代码,它是有效的。但是,如果您正在分发二进制文件,则它是不可靠的。该值是在编译期间确定的。

      【讨论】:

      • 幸运的是,C 不是“一次编译,到处运行”。
      猜你喜欢
      • 2011-01-31
      • 2011-07-13
      • 1970-01-01
      • 2011-12-15
      • 2017-01-08
      • 1970-01-01
      • 2011-10-24
      • 2011-06-29
      • 1970-01-01
      相关资源
      最近更新 更多