据我所知,当你在C中使用左移位运算符时,它保证空位将填充为0。但是,我已经读到右移是依赖于实现的,这意味着在一些机器中空位将填充0,而在其他机器中它们将填充1。
我在程序中使用右移,实际上我的机器用1填充空位。问题是我需要用0来填充。
有没有办法强制在正确的班次使用0?
在应用右移后,一种解决方案是创建一个类似011111111的掩码,然后应用按位AND,这将更改插入的最左边的1。
但这很麻烦,浪费时间。如果有办法告诉我的机器用1s填充正确的班次,那就更容易了。
由于
答案 0 :(得分:39)
将数字转换为unsigned
,然后转移。这将迫使0填充。
答案 1 :(得分:17)
不,你不能。
无符号类型的移位定义良好(只要右操作数为非负数且小于左操作数的宽度),并且它们始终为零填充。
签名类型的移位(或任何按位操作)通常不是一个好主意。如果左操作数为负,则<<
具有未定义的行为,>>
产生实现定义的结果(意味着编译器必须记录它的作用,但是你无法控制它) 。对于有符号类型的非负值,结果就是您所期望的 - 只要它不溢出(如果它溢出,则行为未定义)。
以下是C99 standard所说的内容(第6.5.7节):
对每个操作数执行整数提升。类型 结果是提升左操作数的结果。如果值 右操作数为负数或大于或等于宽度 在提升的左操作数中,行为未定义。
E1 的结果&lt;&lt; E2 是 E1 左移 E2 位 位置;腾出的位用零填充。如果 E1 有未签名的 类型,结果的值是 E1 ×2 E2 ,减少模数 比结果类型中可表示的最大值。如果 E1 有 有符号类型和非负值, E1 ×2 E2 可表示 结果类型,那就是结果值;否则, 行为未定义。
E1 的结果&gt;&gt; E2 是 E1 右移 E2 位位置。如果 E1 有 无符号类型或 E1 具有签名类型和非负值, 结果的值是 E1 /的商的组成部分 2 的 E2 强> 。如果 E1 具有签名类型和负值,则生成 值是实现定义的。
答案 2 :(得分:5)
有两种不同的右移操作:算术和逻辑。
逻辑移位与C中的无符号数一起使用。它总是用零填充高位。这就是你需要的。
算术移位与带符号的数字一起使用,因为它保留了移位数字的符号。如果数字为正,则最高有效位为0,并且将填充0。如果数字为负数,则最高有效位为1,因此将填充1。
请注意,在Java中,这些实际上使用不同的运算符:>>
用于算术,>>>
用于逻辑。这是必需的,因为Java没有无符号类型。