C标准支持的平台列表

时间:2021-08-01 17:06:46

Does anyone know of any platforms supported by the C standard, for which there is still active development work, but which are:

有谁知道C标准支持的任何平台,目前仍有积极的开发工作,但包括:

  • not 2's complement or
  • 不是2的补充或
  • the integer width is not 32 bits or 64 bits or
  • 整数宽度不是32位或64位。
  • some integer types have padding bits or
  • 有些整数类型具有填充位或
  • if you worked on a 2's complement machine, the bit pattern with sign bit 1 and all value bits zero is not a valid negative number or
  • 如果在2的补码机上工作,带符号位1和所有值位为零的位模式不是一个有效的负数或
  • integer conversion from signed to unsigned (and vice versa) is not via verbatim copying of bit patterns or
  • 从有符号到无符号的整数转换(反之亦然)不是通过位模式的逐字复制实现的
  • right shift of integer is not arithmetic shift or
  • 整数的右移位不是算术移位
  • the number of value bits in an unsigned type is not the number of value bits in the corresponding signed type + 1 or
  • 无符号类型中的值位数不是对应的有符号类型+ 1或中的值位数
  • conversion from a wider int type to a smaller type is not by truncation of the left most bits which would not fit
  • 从更宽的int类型到更小的类型的转换不是通过截断左大部分不适合的位进行的

EDIT: Alternatively, if there are platforms in the period 1995 to 1998 which influenced the C99 decision to include the above, but which were discontinued, I would be interested in them also.

编辑:另外,如果1995年至1998年期间有平台影响了C99将上述内容包括在内的决定,但这些平台已经停止使用,我也会对它们感兴趣。

EDIT: The C rationale has this to say about padding bits:

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

Padding bits are user-accessible in an unsigned integer type. For example, suppose a machine uses a pair of 16-bit shorts (each with its own sign bit) to make up a 32-bit int and the sign bit of the lower short is ignored when used in this 32-bit int. Then, as a 32-bit signed int, there is a padding bit (in the middle of the 32 bits) that is ignored in determining the value of the 32-bit signed int. But, if this 32-bit item is treated as a 32-bit unsigned int, then that padding bit is visible to the user’s program. The C committee was told that there is a machine that works this way, and that is one reason that padding bits were added to C99.

填充位在无符号整数类型中是用户可访问的。例如,假设一台机器使用一个16位的短裤(每个都有自己的符号位)组成一个32位整数的符号位低短使用时被忽略在这32位整数,然后作为一个32位整数签署,有一个填充比特(中间的32位)被忽略在决定签署的32位int的价值。但是,如果这32位项目视为一个32位无符号整型,然后填充一些用户的程序是可见的。C委员会被告知有一台机器是这样工作的,这也是为什么在C99中加入了填充位。

Footnotes 44 and 45 mention that parity bits might be padding bits. The committee does not know of any machines with user-accessible parity bits within an integer. Therefore, the committee is not aware of any machines that treat parity bits as padding bits.

脚注44和45提到奇偶校验位可能是补位。委员会不知道在一个整数中有任何具有用户可访问的奇偶校验位的机器。因此,委员会不知道有任何机器把奇偶校验位当作填充位。

So another question is, what is that machine which C99 mentioned?

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

EDIT: It seems that C99 was considering removing support for 1's complement and signed magnitude: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n868.htm http://www.open-std.org/jtc1/sc22/wg14/www/docs/n873.htm (search for 6.2.6.2)

编辑:看来C99正在考虑取消对1的补码和签名大小的支持:http://www.open-std.org/jtc1/sc22/ wg14/wwwg14/wwwg/docs/n868.m http://www.open- std.org/jtc1/sc22/wg14/wwwg/docs/n873.m(搜索6.6.2)

7 个解决方案

#1


11  

I recently worked at a company which still used a version of the PDP-10, and a port of GCC to that platform. The 10 we used had a few of the attributes you list:

我最近在一家公司工作,该公司还使用了版本的PDP-10和一个GCC的端口。我们使用的10个属性中有一些是你列出的:

  • Integers are not 32 or 64 bits they are 36 bits wide.
  • 整数不是32或64位,而是36位宽。
  • Padding bits are used for some representations. For extended precision integers (e.g. of long long type), the underlying representation was 72-bits in which each of the 36-bit words had a sign-bit.
  • 填充位用于某些表示。对于扩展的精度整数(例如long long类型),底层表示是72位,其中每一个36位单词都有一个符号位。

In addition to the above unusual attributes, there was the issue that the machine had several different byte addressing mechanisms. Bytes with widths in the range of 6-12 bits wide could be addressed by using special bits in the address itself which indicated which width and word alignment was being used. To represent a char* one could use a representation which would address 8-bit bytes, all of which were left-aligned in the word, leaving 4-bits in each 36-bit word which were not addressed at all. Alternatively 9-bit bytes could be used which would fit evenly into the 36-bit word. Both such approaches had there pitfalls for portability, but at the time I left it was deemed more practical to use the 8-bit bytes because of interaction with TCP/IP networking and standard devices which often think in terms of 16, 24, or 32-bit fields which also have an underlying structure of 8-bit bytes.

除了上述不寻常的属性之外,还有一个问题是机器有几个不同的字节寻址机制。宽度在6-12位范围内的字节可以通过在地址本身中使用特殊的位来寻址,这些位指出正在使用的宽度和字的对齐。要表示一个char*,我们可以使用一个表示,它将处理8位字节,所有这些字节都是左对齐的,在每个36位的字中留下4位,而这些字根本没有被处理。也可以使用9位字节,它可以均匀地放入36位字中。可移植性等方法都有缺陷,但当时我把它视为更实际使用8位字节,因为与TCP / IP网络和标准设备通常考虑16日24日或32位字段也有一个8位字节的底层结构。

As far as I know this platform is still being used in products in the field, and there is a compiler developer at this company keeping relatively recent versions of GCC up to date in order to allow for further C development on this platform.

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

#2


12  

It should be noted that you cannot rely on undefined behaviour even on commonly used platforms, because modern optimizing compilers perform program transformations that only preserve defined behaviour.

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

In particular, you cannot rely on two's complement arithmetic giving you INT_MAX+1 == INT_MIN. For example, gcc 4.6.0 optimizes the following into an infinite loop:

特别地,你不能依赖于2的补码运算来给出INT_MAX+1 == INT_MIN。例如,gcc 4.6.0将以下优化为一个无限循环:

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

EDIT: See here for more on signed overflow and GCC optimizations.

编辑:更多关于已签名溢出和GCC优化的信息,请参见这里。

#3


11  

About a decade ago we had to port our C embedded database to a DSP processor that happened to be the main processor of a car stereo. It was a 24-bit machine, in the worst way: sizeof(char) == sizeof(int) == sizeof(void*) == 1, which was 24 bits. We named the branch that dealt with this port "24-bit hell".

大约十年前,我们不得不将我们的C嵌入式数据库移植到DSP处理器上,而DSP处理器恰好是汽车立体声系统的主要处理器。这是一台24位的机器,最坏的情况是:sizeof(char) = sizeof(int) = sizeof = sizeof(void*) = 1,即24位。我们把处理这个端口的分支命名为“24位地狱”。

Since then we ported our library to many platforms, but none as weird as that. They may still be out there (cheap 24-bit DSP chips are even cheaper now), found in low-cost devices where ease of programming is a distant second to a low bill of materials (BOM). Come to think of it, I think we did encounter a machine where a right shift of an unsigned integer did not necessarily insert zero bits. Even so, highly nonstandard arithmetic rules on a platform guarantee challenging, error-prone porting of software to it, which dramatically increases software development costs. At some point sanity prevails and standards are observed.

从那时起,我们将库移植到许多平台上,但没有一个平台比这更奇怪。它们可能仍然存在(廉价的24位DSP芯片现在甚至更便宜),在低成本设备中可以找到,在那里,编程的易用性远远落后于低成本材料(BOM)。回想一下,我认为我们确实遇到过这样的机器:一个无符号整数的右移位不一定要插入零位。即便如此,平台上的高度非标准的算术规则保证了向其移植软件的挑战性和易出错性,这极大地增加了软件开发成本。在某种程度上,理智占上风,标准得到遵守。

I suspect that a lot of the motivation for the presence of these rules in C99 is their presence in C89, and earlier iterations of the language. Don't forget that when C was invented, computers were a lot more diverse than they are today. "Bit-slice" processor designs were available where you could add as many bits as you wanted to your processor just by adding chips. And before C you had to code in assembly language or worry about exactly where in RAM your code would reside, etc.

我怀疑在C99中出现这些规则的很多动机是它们在C89中的存在,以及早期的语言迭代。别忘了C被发明的时候,电脑比现在多样化多了。“位片”处理器设计可用,只需添加芯片,就可以向处理器添加任意数量的位。在C语言出现之前,你必须用汇编语言编写代码,或者担心你的代码在RAM中的确切位置,等等。

C was a dramatic step forward in terms of portability, but it had to corral a diverse range of systems, hence the very general rules. 20 years later, when Java came around, it had the benefit of history to allow it to declare up-front how big primitive types were to be, which makes everything a lot easier, as long as Java's choices are sound.

就可移植性而言,C是向前迈出的一大步,但它必须限制各种各样的系统,因此才有非常普遍的规则。20年后,当Java出现时,历史的好处是允许它预先声明原始类型的大小,只要Java的选择是合理的,这就使一切变得容易得多。

I know you are mostly asking about integers, but I have encountered some weirdness when it comes to pointers. Early Macintosh computers had 32-bit processors (Motorola 68000), but only 24-bit memory busses. Thus 0x00123456 and 0xFF123456 referred to the same memory cell, because the processor chopped off the upper 8 bits when accessing RAM. Apple engineers used these bits to store metadata about the memory that the pointer pointed to. Thus when comparing pointers, one had to mask off the upper bits first. And don't get me started on the segmented memory architectures of the x86. :)

我知道你问的大多是整数,但当涉及到指针时,我遇到了一些奇怪的问题。早期的麦金塔电脑有32位处理器(摩托罗拉68000),但只有24位内存总线。因此0x00123456和0xFF123456引用了同一个内存单元,因为处理器在访问RAM时切断了上面的8位。苹果工程师使用这些位元来存储关于指针指向的内存的元数据。因此,在比较指针时,必须首先屏蔽上位。不要让我开始讲x86的分段内存架构。:)

Since we are on this topic, take a look at the MISRA coding standard, which is favored by makers of automobiles that need maximum portability and safety. Also look at Hacker's Delight by Henry S. Warren, which has tons of useful bit twiddling tricks in it.

既然我们谈到了这个话题,让我们来看看MISRA编码标准,它受到了需要最大可移植性和安全性的汽车制造商的青睐。看看亨利·s·沃伦(Henry S. Warren)的《骇客的喜悦》(Hacker’s Delight),这本书里有很多有用的小窍门。

#4


6  

My two cents. Please don't blame hard, this is from my experience, I'm not a theoretic:

我的两个美分。请不要责怪我,这是我的经验,我不是一个理论学家:

  • not 2's complement
  • 不是2的补

All of the existing CPU's are 2's complement

所有现有的CPU都是2的补码。

  • the integer width is not 32 bits or 64 bits
  • 整数宽度不是32位或64位

There are 8 and 16 bits architectures too. 8 bit AVR MCU's is a good example.

还有8位和16位架构。8位AVR单片机就是一个很好的例子。

  • some integer types have padding bits
  • 一些整数类型有填充位。

I am not aware of any system, that pads integers. Floating numbers - is a different story.

我不知道任何一个系统,它会覆盖整数。浮动数字-是一个不同的故事。

  • if you worked on a 2's complement machine, the bit pattern with sign bit 1 and all value bits zero is not a valid negative number
  • 如果在2的补码机上工作,带符号位1和所有值位为零的位模式不是一个有效的负数
  • integer conversion from signed to unsigned (and vice versa) is not via verbatim copying of bit patterns
  • 从有符号到无符号(反之亦然)的整数转换不是通过位模式的逐字复制实现的
  • right shift of integer is not arithmetic shift
  • 整数的右移位不是算术移位
  • the number of value bits in an unsigned type is not the number of value bits in the corresponding signed type + 1
  • 无符号类型中的值位数不是对应的有符号类型+ 1中的值位数
  • conversion from a wider int type to a smaller type is not by truncation of the left most bits which would not fit
  • 从更宽的int类型到更小的类型的转换不是通过截断左大部分不适合的位进行的

All of the above - not aware of any, and I assume there is no such machine.

以上所有的一切-没有任何意识到,我假设没有这样的机器。

#5


6  

Even if these machines are ancient, there's still an active community programming for PDP-8, most but not all using simulations: PDP-8 as an example. And this machine, AFAIK, uses 12-bit integers!

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

#6


4  

The cc65 compiler for Commodore C64 seem to have had some update as late as last year.

Commodore C64的cc65编译器似乎早在去年就进行了一些更新。

#7


3  

An old adage (I forgot the attribution) says that

一句古老的谚语(我忘记了出处)是这么说的

there is no such thing as portable code

没有所谓的可移植代码

But only that there are some code which have been ported.

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

You should not care about writing portable code, you should care about writing code that will be easy to port to other platforms.

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

Besides, using only the C standard gives you not many useful things. Posix standards gives you much more.

此外,只使用C标准不会带来很多有用的东西。Posix标准提供了更多。

#1


11  

I recently worked at a company which still used a version of the PDP-10, and a port of GCC to that platform. The 10 we used had a few of the attributes you list:

我最近在一家公司工作,该公司还使用了版本的PDP-10和一个GCC的端口。我们使用的10个属性中有一些是你列出的:

  • Integers are not 32 or 64 bits they are 36 bits wide.
  • 整数不是32或64位,而是36位宽。
  • Padding bits are used for some representations. For extended precision integers (e.g. of long long type), the underlying representation was 72-bits in which each of the 36-bit words had a sign-bit.
  • 填充位用于某些表示。对于扩展的精度整数(例如long long类型),底层表示是72位,其中每一个36位单词都有一个符号位。

In addition to the above unusual attributes, there was the issue that the machine had several different byte addressing mechanisms. Bytes with widths in the range of 6-12 bits wide could be addressed by using special bits in the address itself which indicated which width and word alignment was being used. To represent a char* one could use a representation which would address 8-bit bytes, all of which were left-aligned in the word, leaving 4-bits in each 36-bit word which were not addressed at all. Alternatively 9-bit bytes could be used which would fit evenly into the 36-bit word. Both such approaches had there pitfalls for portability, but at the time I left it was deemed more practical to use the 8-bit bytes because of interaction with TCP/IP networking and standard devices which often think in terms of 16, 24, or 32-bit fields which also have an underlying structure of 8-bit bytes.

除了上述不寻常的属性之外,还有一个问题是机器有几个不同的字节寻址机制。宽度在6-12位范围内的字节可以通过在地址本身中使用特殊的位来寻址,这些位指出正在使用的宽度和字的对齐。要表示一个char*,我们可以使用一个表示,它将处理8位字节,所有这些字节都是左对齐的,在每个36位的字中留下4位,而这些字根本没有被处理。也可以使用9位字节,它可以均匀地放入36位字中。可移植性等方法都有缺陷,但当时我把它视为更实际使用8位字节,因为与TCP / IP网络和标准设备通常考虑16日24日或32位字段也有一个8位字节的底层结构。

As far as I know this platform is still being used in products in the field, and there is a compiler developer at this company keeping relatively recent versions of GCC up to date in order to allow for further C development on this platform.

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

#2


12  

It should be noted that you cannot rely on undefined behaviour even on commonly used platforms, because modern optimizing compilers perform program transformations that only preserve defined behaviour.

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

In particular, you cannot rely on two's complement arithmetic giving you INT_MAX+1 == INT_MIN. For example, gcc 4.6.0 optimizes the following into an infinite loop:

特别地,你不能依赖于2的补码运算来给出INT_MAX+1 == INT_MIN。例如,gcc 4.6.0将以下优化为一个无限循环:

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

EDIT: See here for more on signed overflow and GCC optimizations.

编辑:更多关于已签名溢出和GCC优化的信息,请参见这里。

#3


11  

About a decade ago we had to port our C embedded database to a DSP processor that happened to be the main processor of a car stereo. It was a 24-bit machine, in the worst way: sizeof(char) == sizeof(int) == sizeof(void*) == 1, which was 24 bits. We named the branch that dealt with this port "24-bit hell".

大约十年前,我们不得不将我们的C嵌入式数据库移植到DSP处理器上,而DSP处理器恰好是汽车立体声系统的主要处理器。这是一台24位的机器,最坏的情况是:sizeof(char) = sizeof(int) = sizeof = sizeof(void*) = 1,即24位。我们把处理这个端口的分支命名为“24位地狱”。

Since then we ported our library to many platforms, but none as weird as that. They may still be out there (cheap 24-bit DSP chips are even cheaper now), found in low-cost devices where ease of programming is a distant second to a low bill of materials (BOM). Come to think of it, I think we did encounter a machine where a right shift of an unsigned integer did not necessarily insert zero bits. Even so, highly nonstandard arithmetic rules on a platform guarantee challenging, error-prone porting of software to it, which dramatically increases software development costs. At some point sanity prevails and standards are observed.

从那时起,我们将库移植到许多平台上,但没有一个平台比这更奇怪。它们可能仍然存在(廉价的24位DSP芯片现在甚至更便宜),在低成本设备中可以找到,在那里,编程的易用性远远落后于低成本材料(BOM)。回想一下,我认为我们确实遇到过这样的机器:一个无符号整数的右移位不一定要插入零位。即便如此,平台上的高度非标准的算术规则保证了向其移植软件的挑战性和易出错性,这极大地增加了软件开发成本。在某种程度上,理智占上风,标准得到遵守。

I suspect that a lot of the motivation for the presence of these rules in C99 is their presence in C89, and earlier iterations of the language. Don't forget that when C was invented, computers were a lot more diverse than they are today. "Bit-slice" processor designs were available where you could add as many bits as you wanted to your processor just by adding chips. And before C you had to code in assembly language or worry about exactly where in RAM your code would reside, etc.

我怀疑在C99中出现这些规则的很多动机是它们在C89中的存在,以及早期的语言迭代。别忘了C被发明的时候,电脑比现在多样化多了。“位片”处理器设计可用,只需添加芯片,就可以向处理器添加任意数量的位。在C语言出现之前,你必须用汇编语言编写代码,或者担心你的代码在RAM中的确切位置,等等。

C was a dramatic step forward in terms of portability, but it had to corral a diverse range of systems, hence the very general rules. 20 years later, when Java came around, it had the benefit of history to allow it to declare up-front how big primitive types were to be, which makes everything a lot easier, as long as Java's choices are sound.

就可移植性而言,C是向前迈出的一大步,但它必须限制各种各样的系统,因此才有非常普遍的规则。20年后,当Java出现时,历史的好处是允许它预先声明原始类型的大小,只要Java的选择是合理的,这就使一切变得容易得多。

I know you are mostly asking about integers, but I have encountered some weirdness when it comes to pointers. Early Macintosh computers had 32-bit processors (Motorola 68000), but only 24-bit memory busses. Thus 0x00123456 and 0xFF123456 referred to the same memory cell, because the processor chopped off the upper 8 bits when accessing RAM. Apple engineers used these bits to store metadata about the memory that the pointer pointed to. Thus when comparing pointers, one had to mask off the upper bits first. And don't get me started on the segmented memory architectures of the x86. :)

我知道你问的大多是整数,但当涉及到指针时,我遇到了一些奇怪的问题。早期的麦金塔电脑有32位处理器(摩托罗拉68000),但只有24位内存总线。因此0x00123456和0xFF123456引用了同一个内存单元,因为处理器在访问RAM时切断了上面的8位。苹果工程师使用这些位元来存储关于指针指向的内存的元数据。因此,在比较指针时,必须首先屏蔽上位。不要让我开始讲x86的分段内存架构。:)

Since we are on this topic, take a look at the MISRA coding standard, which is favored by makers of automobiles that need maximum portability and safety. Also look at Hacker's Delight by Henry S. Warren, which has tons of useful bit twiddling tricks in it.

既然我们谈到了这个话题,让我们来看看MISRA编码标准,它受到了需要最大可移植性和安全性的汽车制造商的青睐。看看亨利·s·沃伦(Henry S. Warren)的《骇客的喜悦》(Hacker’s Delight),这本书里有很多有用的小窍门。

#4


6  

My two cents. Please don't blame hard, this is from my experience, I'm not a theoretic:

我的两个美分。请不要责怪我,这是我的经验,我不是一个理论学家:

  • not 2's complement
  • 不是2的补

All of the existing CPU's are 2's complement

所有现有的CPU都是2的补码。

  • the integer width is not 32 bits or 64 bits
  • 整数宽度不是32位或64位

There are 8 and 16 bits architectures too. 8 bit AVR MCU's is a good example.

还有8位和16位架构。8位AVR单片机就是一个很好的例子。

  • some integer types have padding bits
  • 一些整数类型有填充位。

I am not aware of any system, that pads integers. Floating numbers - is a different story.

我不知道任何一个系统,它会覆盖整数。浮动数字-是一个不同的故事。

  • if you worked on a 2's complement machine, the bit pattern with sign bit 1 and all value bits zero is not a valid negative number
  • 如果在2的补码机上工作,带符号位1和所有值位为零的位模式不是一个有效的负数
  • integer conversion from signed to unsigned (and vice versa) is not via verbatim copying of bit patterns
  • 从有符号到无符号(反之亦然)的整数转换不是通过位模式的逐字复制实现的
  • right shift of integer is not arithmetic shift
  • 整数的右移位不是算术移位
  • the number of value bits in an unsigned type is not the number of value bits in the corresponding signed type + 1
  • 无符号类型中的值位数不是对应的有符号类型+ 1中的值位数
  • conversion from a wider int type to a smaller type is not by truncation of the left most bits which would not fit
  • 从更宽的int类型到更小的类型的转换不是通过截断左大部分不适合的位进行的

All of the above - not aware of any, and I assume there is no such machine.

以上所有的一切-没有任何意识到,我假设没有这样的机器。

#5


6  

Even if these machines are ancient, there's still an active community programming for PDP-8, most but not all using simulations: PDP-8 as an example. And this machine, AFAIK, uses 12-bit integers!

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

#6


4  

The cc65 compiler for Commodore C64 seem to have had some update as late as last year.

Commodore C64的cc65编译器似乎早在去年就进行了一些更新。

#7


3  

An old adage (I forgot the attribution) says that

一句古老的谚语(我忘记了出处)是这么说的

there is no such thing as portable code

没有所谓的可移植代码

But only that there are some code which have been ported.

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

You should not care about writing portable code, you should care about writing code that will be easy to port to other platforms.

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

Besides, using only the C standard gives you not many useful things. Posix standards gives you much more.

此外,只使用C标准不会带来很多有用的东西。Posix标准提供了更多。