C#中位移旋转操作的问题

3

在C++中,我有这样的代码。

    static UInt32 rol(UInt32 value, UInt32 bits)
    {
        bits &= 31;
        return ((value << bits) | (value >> (32 - bits)));
    }

    static UInt32 ror(UInt32 value, UInt32 bits)
    {
        bits &= 31;
        return ((value >> bits) | (value << (32 - bits)));
    }

在C#中应该是这个样子的。只有一个问题

错误2 运算符“>>”无法应用于类型为“uint”的操作数和类型为“uint”的操作数
错误3 运算符“>>”无法应用于类型为“uint”的操作数和类型为“uint”的操作数
错误1 运算符“<<”无法应用于类型为“uint”的操作数和类型为“uint”的操作数
错误4 运算符“<<”无法应用于类型为“uint”的操作数和类型为“uint”的操作数


记录一下:编译器友好的表达旋转的最佳实践,避免C未定义行为:https://dev59.com/J3RA5IYBdhLWcg3w8SiJ。当`bits == 0时,此代码将通过32位移动32b value`。希望在C#中这是合法的。 - Peter Cordes
4个回答

3
您应该在移位运算符的右侧变量中使用int类型。

但这样不会影响 bits &= 31; 的逻辑吗?我需要在那之后再创建一个变量吗?如果我只是将 UInt32 bits 更改为 int bits,那么一切都可以解决,但是 bits AND 31 的逻辑会出问题吗? - SSpoke
你可以用 bits %= 32 替换 bits &= 31 - oxilumin
为什么要使用合约?是为了避免异常吗?我在我的.NET框架中找不到那个库。 - SSpoke
这只是一种在一个字符串中编写 if then throw 表达式的方法,此外 - 您可以使用代码合同库进行静态检查。您可以在 微软网站 上了解更多信息。 - oxilumin
@SSpoke:不,var &= 31; 的结果不受有符号性的影响。有符号性仅改变最高有效位的含义。 - Ben Voigt

1

右操作数必须始终为 int 类型。

 int x << int bits
 uint x << int bits
 long x << int bits
 ulong x << int bits

1
你需要将位移运算符的右侧转换为整型。如果你像这样进行转换 (int)(32 - bits),它不应该影响你的预期目的。右侧只是期望一个整数,可能是因为这样更简单,并且你很少会想要移动超过20亿个位。

算了,我选择了你的解决方案... 更简单的修复方法.. return ((value << (int)bits) | (value >> (int)(32 - bits)));return ((value >> (int)bits) | (value << (int)(32 - bits))); - SSpoke

0

加上一些括号就可以了:

byte[] bytes = { 1, 2, 4, 8 };
UInt32 crc32 = ((UInt32)msg.Data[3] << 24) +
    ((UInt32)msg.Data[2] << 16) +
    ((UInt32)msg.Data[1] << 8) +
    msg.Data[0];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接