1

如果对应于有符号整数的位模式向右移动,则

1   vacant bit will be filled by the sign bit   
2   vacant bit will be filled by 0  
3   The outcome is implementation dependent 
4   none of the above

这个问题的答案是第三个选项.. 任何人都可以解释这个,,

还给出一些基本概念,关于 C 编程中左移和右移运算符背后的理论。例如

执行任何操作时在空位上填充的内容。我检查并注意到左移将空位填充0,右移填充1。请清除逻辑...

4

5 回答 5

6

我必须检查规范以了解究竟是什么依赖于实现的问题。然而,我在(咕哝)多年的嵌入式系统项目中使用的每一个实现都是明智的:

  • 左移总是在低位移入 0。没有其他值是有意义的。

  • 右移取决于数据类型。有符号整数的右移会复制高位,因为它将其余部分右移。这被称为“算术移位”,并且具有很好的特性(至少在二进制补码算术中),它将值除以二,同时保留原始数字的符号。

    无符号整数的右移将 0 移到高位,通常称为“逻辑移位”。

实现提供两种转换是有意义的,因为两者都很有用,并且使用有符号/无符号来选择意味着是一个明智的选择。

编辑:至少绝对依赖于实现的一件事是C标准没有(完全)指定整数的底层实现及其存储。例如,可以为使用补码算法的机器构建兼容的 C 编译器。也有可能(我认为)为一台机器构建一个兼容的编译器,它的本机存储是有符号 BCD 大小的。(不,我错了,见下文。)

在实践中,世界几乎已经确定了 CPU 的二进制补码,并且一些迂腐的问题正在讨论中。

所以问题的一部分实际上是:如何以稳定的方式定义 << 和 >> 运算符的含义,而不管使用的底层算术系统如何。

IIRC, 的定义n<<1是有效n*2的,n>>1是有效n/2的, 具有超过 1 的自然扩展(但不超过 31...那里有未定义的龙...) 并且>>操作员将保留如果对有符号值进行操作,则为符号。

编辑 2: Pete Kirkham 在他的好回答中指出,C 标准确实特别禁止整数的 BCD 表示的可怕情况,无论它是有符号的幅度还是十的补码。我确信这是一件好事,即使 Knuth 在早期版本的The Art of Computer Programming中确实使用(可选)BCD 机器作为他的示例代码。

在那些 BCD 是正确答案的罕见用例中,然后将它们存储在无符号长整数(8 位十位补码)或无符号 64 位整数(16 位十位补码或 15 位加号和标志的空间)中,并使用精心设计的算术库来操作它们是有意义的。

当然,在实践中,C 实现将操作符按照标准允许的方式直接映射到 CPU 的本机机器指令。编写标准的人非常注意存在许多方法来实现甚至简单的事情,比如整数值的表示,而 C 标准反映了这一点,通过允许足够的实现定义的行为来让运算符在每个机器。

替代方案迅速导致所有数学运算都完全指定的世界,并且无法在任何机器上有效地实现。

于 2009-03-17T07:34:05.137 回答
5

C 不保证存在符号位,或者关于整数的位级表示的任何内容,这就是原因。

对于二进制补码,您通常会看到符号位被移入,但这取决于实现。

于 2009-03-17T07:30:14.880 回答
2

ISO C99 在表示的某处需要一个符号位,但提供了各种补码/符号和幅度方案之间的选项,并允许填充位,所有这些都会影响>>.

第 6.2.6.2 节(整数类型)

对于有符号整数类型,对象表示的位应分为三组:值位、填充位和符号位。不需要任何填充位;应该只有一个符号位。

第 6.5.7 节(按位移位运算符)

E1 >> E2 的结果是 E1 右移 E2 位位置。如果 E1 具有无符号类型或 E1 具有有符号类型和非负值,则结果的值是 E1 / 2 E2的商的整数部分。如果 E1 具有带符号类型和负值,则结果值是实现定义的。

它没有指定使用 1 的补码、2 的补码或符号和幅度中的哪一个,也没有指定符号位是在值位的左边还是右边,或者任何填充在哪里,所有这些都会影响>>运算符的输出签署的底片。

在回答 Rberteig 的查询时,C99 排除了整数的 BCD 表示:

第 6.2.6.2 节(整数类型)

如果有 N 个值位,每个位应表示 1 和 2 N -1 之间的 2 的不同幂,以便该类型的对象应能够使用纯二进制表示表示从 0 到 2 N - 1 的值;这应称为值表示。

于 2009-03-17T10:20:58.777 回答
0

C 语言实现倾向于将位移操作直接映射到相应的机器代码指令上。由于不同的硬件架构在历史上做了不同的事情,C 规范倾向于保留定义的实现,以便 C 实现可以利用硬件提供的任何东西。

于 2009-03-17T07:47:37.007 回答
0

结果取决于实现。然而,在实践中,我曾经使用过的每一个 x86、PPC 和 MIPS 编译器都遵循以下规则来右移:

  1. 如果操作数是有符号整数,则空位用符号位(实际上是最高有效位)填充

  2. 如果操作数是无符号整数,则空位用零填充。

正如 RBerteig 所说,对于有符号整数,正负 n 的 n >> 1 = n/2(向下舍入),对于符号整数,即使 n > 2^,n >> 1 = n/2 31(在 32 位架构上)。

对应的硬件指令是算术(符号扩展)和逻辑(非符号扩展)移位;编译器根据操作数是有符号还是无符号在它们之间进行选择。

于 2009-03-17T07:55:06.427 回答