语言标准规定整数类型可以用以下三种方式之一表示:
- 2的补码,
- 1的补码,
- 有符号值。
在这方面,出现了几个问题:
现在除了2 的补码以外的整数表示吗?
该标准是否允许在同一实现中对整数类型进行不同的表示?例如,什么
char是2 的补码和1int的补码?整数的不同表示如何与按位运算一致?例如,让我们有这样的代码:
unsigned char a = 1; a = ~a;
并让一些实现使用 8 位char和 16位,并使用1 的补码int来表示有符号整数,即 我们在反向代码中存储负值。我的印象是可以进行以下转换来计算变量的值:a
- 该变量将
a进行整数扩展为int,因为根据标准,位否定操作数可以扩展。那些。位集00000001转换为00000000 00000001. - 将发生位反转,即 扩展值变为
11111111 11111110。 - 此位序列将被解释为有符号整数,因为根据标准,位否定的结果是扩展操作数类型。反向代码中的这个位序列表示一个整数
-1。 - 整数
-1将被转换为无符号整数unsigned char模256。那些。该变量a将采用值255,该值由以下位序列编码:11111111。这有点奇怪,因为通过按位否定位序列00000001,我希望得到11111110,而不是11111111。
这种位否定是标准允许的,还是上面的例子根本错误?
他们说像 UNISYS 2200 ( 1 , 2 ) 这样的系统在现实生活中仍然随处可见。这些系统上的默认 C 编译器使用 1 的补码表示法。
也可以看看
是否有任何 C 的非二进制补码实现?
标准委员会关心的异乎寻常的架构
标准中没有直接禁止混合表示。是的,这样的禁令没有任何意义,因为它不会带来任何好处——无论如何,该标准并不保证您在不同有符号整数类型的表示之间有任何“同步”。例如,每个整数类型都可以有自己的数量和填充位排列。
您对操作员工作的解释
~是绝对正确的。是的,这种行为是允许的。是的,在这种情况下“小”无符号类型的行为在很大程度上取决于选择的有符号类型表示。更准确地说,有符号类型的按位行为显然取决于所选择的表示,并且“小”无符号类型已经通过整体提升受制于这种行为。还可以注意到,应用于
~有符号值也可以生成陷阱表示。(在 C89/90 形成过程中选择将 unsigned 类型扩展为signed
int,如 Rationale to the standard 中所述(请参阅我的答案的第二部分here),在这里也发挥了作用,与当时的 Unix不同将无符号类型扩展为的传统unsigned int。)