你能控制C中按位右移填充的内容吗?

ycggw6v2  于 2023-01-29  发布在  其他
关注(0)|答案(3)|浏览(116)

据我所知,当你在C语言中使用按位左移运算符时,可以保证空位会被0填充,然而,我读到过右移是依赖于实现的,这意味着在一些机器中,空位会被0填充,而在另一些机器中,空位会被1填充。
我在一个程序中使用了右移位,我的机器确实用1填充了空位,问题是我需要用0来代替。
有没有办法强迫0在正确的班次使用?
一种解决方案是,在应用右移之后,创建一个类似于011111111的掩码,然后应用逐位AND,这将把插入的最左边的1更改为0。
但这很麻烦,也很浪费时间。如果有一种方法可以告诉我的机器用1来填充正确的班次,那就容易多了。
谢谢

de90aj5v

de90aj5v1#

将数字转换为unsigned,然后按shift。这将强制填充0。

qncylg1j

qncylg1j2#

不,你不能。
无符号类型上的移位是明确定义的(只要右操作数为非负且小于左操作数的宽度),并且它们总是填充零。
班次(或任何按位运算)通常不是一个好主意。如果左操作数为负,则<<具有未定义的行为,并且>>生成实现定义的结果(这意味着编译器必须记录它所做的事情,但您无法控制它)。对于带符号类型的非负值,结果是您所期望的--只要它不溢出(如果溢出,行为是未定义的)。
C99 standard的说明如下(第6.5.7节):
对每个操作数执行整数提升。结果的类型是提升的左操作数的类型。如果右操作数的值为负值,或者大于或等于提升的左操作数的宽度,则行为未定义。

    • E1**〈〈E2的结果是E1左移E2比特位置;空出的位用零填充。如果E1为无符号类型,则结果值为E1× 2E2,比结果类型中可表示的最大值大1的模,如果E1为有符号类型且为非负值,且E1× 2E2可在结果类型中表示,则这就是结果值;否则,该行为是未定义的。
    • E1**〉〉E2的结果是E1右移E2位。如果E1为无符号类型或E1为有符号类型且为非负值,则结果的值为E1/2E2商的整数部分。如果E1为有符号类型且为负值,结果值是实现定义的。

11年多以后再回到这个问题上,一个实现当然可以提供一个选项来控制实现定义的移位行为,我不知道有哪个实现这样做。
我引用的是C99标准,我不相信以后的版本会有相关的变化。

jdgnovmf

jdgnovmf3#

有两种不同的右移操作:算术和逻辑。
在C语言中,逻辑移位用于无符号数。它总是用零填充高位。这就是你需要的。
算术移位用于有符号数,因为它保留了被移位数的符号。如果数为正数,则最高有效位将为0,并且将用0填充。如果数为负数,则最高有效位将为1,因此将用1填充。
注意,在Java中,它们实际上使用不同的操作符:>>表示算术,>>>表示逻辑。这是必需的,因为Java没有无符号类型。

相关问题