【问题标题】:List of platforms supported by the C standardC 标准支持的平台列表
【发布时间】:2021-07-08 20:08:24
【问题描述】:

是否有人知道 C 标准支持的任何平台,这些平台仍在积极的开发工作中,但有:

  • 不是 2 的补码或
  • 整数宽度不是 32 位或 64 位或
  • 某些整数类型具有填充位或
  • 如果您在 2 的补码机器上工作,带符号的位模式 位 1 和所有值位为零不是有效的负数或
  • 从有符号到无符号的整数转换(反之亦然)不是逐字逐句的 位模式的复制或
  • 整数的右移不是算术移位或
  • 无符号类型中的值位数不是 相应有符号类型中的值位 + 1 或
  • 从更宽的 int 类型转换为更小的类型不是通过 截断不适合的最左边的位

编辑:或者,如果在 1995 年至 1998 年期间有平台影响了 C99 决定包括上述内容,但已停产,我也会对它们感兴趣。

编辑:C 的基本原理是关于填充位的:

用户可以在无符号整数类型中访问填充位。例如,假设一台机器 使用一对 16 位的 short(每个都有自己的符号位)组成一个 32 位的 int,并且在这个 32 位的 int 中使用时忽略较低的 short 的符号位。然后,作为 32 位有符号整数,有一个填充位(在 32 位中间)在确定 32 位有符号整数的值时会被忽略。但是,如果这个 32 位项被视为 32 位无符号整数,则该填充位对用户程序是可见的。 C 委员会被告知有一台机器以这种方式工作,这就是在 C99 中添加填充位的原因之一。

脚注 44 和 45 提到奇偶校验位可能是填充位。委员会不 知道任何具有整数内用户可访问奇偶校验位的机器。因此, 委员会不知道有任何机器将奇偶校验位视为填充位。

那么另一个问题是,C99提到的那台机器是什么?

编辑:似乎 C99 正在考虑取消对 1 的补码和有符号幅度的支持:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n868.htmhttp://www.open-std.org/jtc1/sc22/wg14/www/docs/n873.htm(搜索 6.2.6.2)

【问题讨论】:

  • 似乎是某种琐事问题。它是干什么用的?作业?
  • 另外,我怀疑 C 委员会(故意)对人们更新遗留系统的编译器过于乐观。例如参见stackoverflow.com/questions/161797/…——我怀疑那里列出的 1s' 补码系统是否有积极维护的 C99 编译器,但我怀疑 C 委员会希望它可能即使它不太可能实际发生(因此不符合您规定的标准)。
  • 我从未编写过这样的东西,但您应该寻找嵌入式处理器和其他特殊架构方面的奇怪之处。顺便说一句,您应该将CHARBIT != 8 列在您现在在现实世界中很少看到的事物列表中。
  • @Jens: CHAR_BIT != 8 太容易了,不过。有真正的现代 DSP 具有超大字节,因此很容易想象 C 委员会希望 C 在那里适用,而不编译器编写者需要鞭打“C”的表示指针”,它寻址比硬件的自然地址更小的单元。
  • 我认为在您的愿望清单中,您忘记了一个使至少 3、6 变得微不足道的特殊情况:_Bool。在无符号整数类型中明确提到了它。在许多架构上,CHAR_BIT-1 高位是填充位,转换为该类型不会被截断。但这可能不是你想要的。

标签: c standards


【解决方案1】:

我最近在一家公司工作,该公司仍在使用 PDP-10 版本,以及该平台的 GCC 端口。我们使用的 10 个具有您列出的一些属性:

  • 整数不是 32 位或 64 位,而是 36 位宽。
  • 填充位用于某些表示。对于扩展精度整数(例如 long long 类型),基础表示是 72 位,其中每个 36 位字都有一个符号位。

除了上述不寻常的属性外,还有一个问题是机器有几种不同的字节寻址机制。宽度在 6-12 位范围内的字节可以通过使用地址本身中的特殊位来寻址,这些位指示正在使用的宽度和字对齐方式。为了表示一个 char*,可以使用一种表示 8 位字节的表示,所有这些字节都在字中左对齐,在每个 36 位字中留下 4 位根本没有被寻址。或者,可以使用 9 位字节,这将均匀地适合 36 位字。这两种方法都存在可移植性的缺陷,但在我离开的时候,使用 8 位字节被认为更实用,因为它与 TCP/IP 网络和标准设备的交互,通常认为是 16、24 或 32 -bit 字段也具有 8 位字节的底层结构。

据我所知,该平台仍在该领域的产品中使用,并且该公司有一名编译器开发人员保持最新版本的 GCC 为最新版本,以便在该平台上进行进一步的 C 开发。

【讨论】:

    【解决方案2】:

    应该注意的是,即使在常用平台上也不能依赖未定义的行为,因为现代优化编译器执行的程序转换只会保留已定义的行为。

    特别是,您不能依赖二进制补码算法给您INT_MAX+1 == INT_MIN。例如,gcc 4.6.0 将以下优化为无限循环:

    #include <stdio.h>
    int main() {
         int i = 0;
         while (i++ >= 0)
              puts(".");
         return 0;
    }
    

    编辑See here 了解更多关于有符号溢出和 GCC 优化的信息。

    【讨论】:

    • @JonathanLeffler:我最初发布了没有 ++ 运算符的代码,但几乎立即修复了它 - 您的评论是基于旧版本的吗?如果您使用支持二进制补码算法的编译器(其中 0x7fffffff + 1 == -0x80000000 在 32 位机器上),则固定版本的代码会终止。
    • 好的 - ++ 使我的评论不准确......我会删除它。 (是的,我看到的版本没有++,可能是因为我在评论之前没有刷新。)
    • @han:有趣。你知道关于这个特殊案例的更多细节吗?
    • @undur_gongor:有一个很好的 GCC 特定概述 here。 GCC 选项 -fwrapv 强制 2 的补码算法,并且在 IBM XL C/C++ 编译器上,上述优化被 -qstrict_induction 禁用。 GCC 开发人员还坚持说 Intel 编译器进行了类似的循环优化,但我还没有找到与之等效的命令行选项。
    • @han:非常感谢,希望我能多次投票。您应该将链接添加到您的答案中。
    【解决方案3】:

    大约十年前,我们不得不将 C 嵌入式数据库移植到 DSP 处理器上,而该处理器恰好是汽车音响的主处理器。这是一台 24 位机器,最糟糕的是:sizeof(char) == sizeof(int) == sizeof(void*) == 1,它是 24 位的。我们将处理这个端口的分支命名为“24-bit hell”。

    从那时起,我们将我们的库移植到了许多平台,但没有一个比这更奇怪。它们可能仍然存在(便宜的 24 位 DSP 芯片现在甚至更便宜),在低成本设备中可以找到,在这些设备中,编程的便利性远远落后于低物料清单 (BOM)。想一想,我认为我们确实遇到了一台机器,其中无符号整数的右移不一定插入零位。即便如此,平台上高度非标准的算术规则保证了将软件移植到平台上具有挑战性、容易出错,这大大增加了软件开发成本。在某些时候,理智会盛行并遵守标准。

    我怀疑 C99 中出现这些规则的很多动机是它们出现在 C89 和该语言的早期迭代中。不要忘记,当 C 语言被发明时,计算机比今天更加多样化。 “位片”处理器设计是可用的,您只需添加芯片就可以向处理器添加任意数量的位。在 C 之前,您必须使用汇编语言进行编码,或者担心您的代码在 RAM 中的确切位置,等等。

    C 在可移植性方面向前迈出了一大步,但它必须将各种系统集中起来,因此有非常普遍的规则。 20 年后,当 Java 出现时,它得益于历史允许它预先声明原始类型有多大,这使一切变得容易得多,只要 Java 的选择是合理的。

    我知道您主要是在询问整数,但在涉及指针时我遇到了一些奇怪的问题。早期的 Macintosh 计算机具有 32 位处理器(摩托罗拉 68000),但只有 24 位内存总线。因此 0x00123456 和 0xFF123456 指的是同一个内存单元,因为处理器在访问 RAM 时切断了高 8 位。 Apple 工程师使用这些位来存储有关指针指向的内存的元数据。因此,在比较指针时,必须先屏蔽高位。不要让我开始使用 x86 的segmented memory architectures。 :)

    既然我们在这个话题上,请看一下MISRA 编码标准,它受到需要最大便携性和安全性的汽车制造商的青睐。另请查看 Henry S. Warren 的 Hacker's Delight,其中包含大量有用的小技巧。

    【讨论】:

      【解决方案4】:

      我的两分钱。请不要责备,这是我的经验,我不是理论:

      • 不是 2 的补码

      所有现有 CPU 都是 2 的补码

      • 整数宽度不是 32 位或 64 位

      也有 8 位和 16 位架构。 8 位 AVR MCU 就是一个很好的例子。

      • 一些整数类型有填充位

      我不知道 任何 系统,即 pads 整数。浮点数 - 是另一回事。

      • 如果您在 2 的补码机器上工作,则符号位为 1 且所有值位为零的位模式不是有效的负数
      • 从有符号到无符号的整数转换(反之亦然)不是通过逐字复制位模式来实现的
      • 整数的右移不是算术移位
      • 无符号类型的值位数不是对应的有符号类型的值位数+1
      • 从更宽的 int 类型转换为更小的类型不是通过截断最左边不适合的位来实现的

      以上所有 - 不知道任何,我假设没有这样的机器。

      【讨论】:

        【解决方案5】:

        即使这些机器很古老,仍然有一个活跃的 PDP-8 社区编程,大多数但不是全部使用模拟:PDP-8 as an example。 而这台机器,AFAIK,使用 12 位整数!

        【讨论】:

          【解决方案6】:

          Commodore C64 的 cc65 编译器似乎直到去年才进行了一些更新。

          【讨论】:

          • 大概是根据“int不是32位还是64位”来算的吧?它还有其他稀有物品吗?
          • 不,它有 16 位整数(并且没有浮点数,因此不完全符合 ISO 标准),但在其他方面非常接近其他常见平台。此外,用于 DOS 的 C 编译器也有 16 位整数。
          【解决方案7】:

          一句古老的格言(我忘了归属)说

          没有可移植代码这种东西

          但只是有一些代码被移植了。

          你不应该关心编写可移植的代码,你应该关心编写易于移植到其他平台的代码。

          此外,仅使用 C 标准并没有给您带来太多有用的东西。 Posix 标准可以为您提供更多。

          【讨论】:

          【解决方案8】:

          整数宽度不是 32 位或 64 位或

          (几乎)所有平台都有一些既不是 32 也不是 64 位的整数。我想你的意思是 int ? 如果是这样,是的,有很多。有许多微控制器仍在生产中,它们具有 8 位,有时是 16 位内核。他们使用 16 位 int。对于像电压力锅这样的东西来说,在其中安装 32 位处理器并没有多大意义。 PIC10、PIC12、PIC16 和 PIC18 以及 AVR 都不是 8 位的,其中许多仍在生产中。 在您提出这个问题 10 年后的今天,这仍然适用。

          请不要假设 int 至少为 32 位,请使用 uint_least32_tint_least32_tint_fast32_tuint_fast32_tuint32_tint32_tlongunsigned long那。当我看到sizeof(int)*CHAR_BIT==16 时出现中断的代码时,这让我很恼火。

          【讨论】:

            猜你喜欢
            • 2021-09-04
            • 1970-01-01
            • 1970-01-01
            • 2017-06-05
            • 2016-10-18
            • 1970-01-01
            • 1970-01-01
            • 2010-09-11
            相关资源
            最近更新 更多