显然,标准对此只字未提,但从实际/历史的角度来看,我更感兴趣:具有非二进制补码算术的系统是否使用char
无符号的普通类型?否则,您可能会遇到各种奇怪的情况,例如 null 终止符的两种表示形式,以及无法表示char
. 这种奇怪的系统真的存在吗?
3 回答
用于终止字符串的空字符永远不能有两种表示形式。它是这样定义的(即使在 C90 中):
所有位都设置为 0 的字节,称为空字符,应存在于基本执行字符集中
因此,补码上的“负零”是行不通的。
也就是说,我真的对非二进制补码 C 实现知之甚少。我在大学时使用了一个补码机器,但不太记得它(即使我当时关心标准,它还是在它存在之前)。
确实,在商业生产的计算机的前 10 年或 20 年(1950 年代和 60 年代),对于如何用二进制表示负数,显然存在一些分歧。实际上有三个竞争者:
- 二的补码,不仅赢得了战争,而且将其他人推向了灭亡
- 一个人的补充,
-x == ~x
- 符号大小,
-x = x ^ 0x80000000
我认为最后一个重要的互补机器可能是 CDC-6600,它在当时是地球上最快的机器,也是第一台超级计算机的直接前身。1.
不幸的是,您的问题无法真正得到回答,不是因为这里没有人知道答案:-) 而是因为永远不必做出选择。这实际上有两个原因:
二进制补码与字节机同时接管。字节寻址通过二进制补码 IBM System/360 风靡全球。以前的机器没有字节,只有完整的字有地址。有时程序员会在这些单词中包含字符,有时他们会使用整个单词。(字长从 12 位到 60 位不等。)
直到字节机和二进制补码过渡十年后才发明了 C。第 1 项发生在 1960 年代,C 在 1970 年代首次出现在小型机器上,直到 1980 年代才接管世界。
因此,机器从未有过有符号字节、C 编译器和二进制补码数据格式以外的其他东西。空终止字符串的想法可能是一个汇编语言程序员一个又一个反复发明的设计模式,但我不知道它是由编译器指定的,直到 C 时代。
在任何情况下,第一个实际标准化的 C (“C89”)只是指定“附加一个字节或值为零的代码”,并且从上下文中可以清楚地看出它们试图独立于数字格式。所以,“+0”是一个理论上的答案,但实际上它可能永远不会真正存在。
1. 6600 是历史上最重要的机器之一,不仅仅是因为它速度快。它由 Seymour Cray 自己设计,引入了乱序执行和各种其他元素,后来统称为“RISC”。尽管其他人试图声称功劳,但 Seymour Cray 是 RISC 架构的真正发明者。毫无疑问,他发明了超级计算机。实际上很难说出不是他设计的过去的“超级计算机”。
我相信一个系统几乎但不太可能有一个补码'char'类型,但是有四个问题不能全部解决:
- 每个数据类型都必须可以表示为一个 char 序列,这样如果包含两个对象的所有 char 值比较相同,则包含的数据对象将是相同的。
- 每种数据类型都必须同样可以表示为“无符号字符”序列。
- 可以将任何数据类型分解成的 unsigned char 值必须形成一个组,其顺序是 2 的幂。
- 我不相信该标准允许一个补码机器对负零的值进行特殊处理并使其表现得像其他东西。
如果获得负零的唯一方法是覆盖一些其他数据类型,并且如果负零比较不等于正,则可能有一个符合标准的机器具有一个补码或符号大小“char”类型零。我不确定这是否符合标准。
编辑
顺便说一句,如果放宽要求#2,我想知道将其他数据类型覆盖到“char”上时的确切要求是什么?除其他事项外,虽然该标准非常清楚地表明,必须能够对可能由于将另一个变量覆盖到“char”上而产生的任何“char”值执行赋值和比较,但我不知道它是否有任何要求所有这些值都必须表现为算术组。例如,我想知道一台机器的合法性是什么,其中每个内存位置物理存储为 66 位,前两位表示该值是否是 64 位整数、32 位内存句柄加上 32 -位偏移,还是 64 位双精度浮点数?由于该标准允许实现在算术计算超出有符号类型的范围时做任何他们喜欢的事情,这表明有符号类型不一定必须表现为一个组。
对于大多数有符号类型,不要求该类型不能表示超出limits.h 中指定范围的任何数字;如果limits.h 指定最小“int”是-32767,那么实现实际上允许-32768 的值是完全合法的,因为任何尝试这样做的程序都会调用未定义的行为。关键问题可能是,由某些其他类型的覆盖产生的“char”值是否合法,以产生超出limits.h中指定范围的值。我想知道标准是怎么说的?