Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#按位向左旋转和向右旋转 < > >代码> > RoLL和>ROTR C++中的位旋转的内置语言特征是什么?但是这些扩展方法应该做的工作是: public static uint RotateLeft(this uint value, int count) { return (value << count) | (value >> (32 - count)) } public static uint RotateRight(this uint value, int count) { return (value >> count) | (value << (32 - count)) }_C#_Bitwise Operators - Fatal编程技术网

C#按位向左旋转和向右旋转 < > >代码> > RoLL和>ROTR C++中的位旋转的内置语言特征是什么?但是这些扩展方法应该做的工作是: public static uint RotateLeft(this uint value, int count) { return (value << count) | (value >> (32 - count)) } public static uint RotateRight(this uint value, int count) { return (value >> count) | (value << (32 - count)) }

C#按位向左旋转和向右旋转 < > >代码> > RoLL和>ROTR C++中的位旋转的内置语言特征是什么?但是这些扩展方法应该做的工作是: public static uint RotateLeft(this uint value, int count) { return (value << count) | (value >> (32 - count)) } public static uint RotateRight(this uint value, int count) { return (value >> count) | (value << (32 - count)) },c#,bitwise-operators,C#,Bitwise Operators,(请注意,int.MinValue是111111111111-32 1s的二进制格式。)这就是您想要做的吗 基本上你想要的是 (左) (原始>(32位)) 或 (右图) (原始>>位)|(原始原始版本的移位不起作用。原因是,右移位有符号数将用符号位填充左位,而不是0: 您可以通过以下方式验证此事实: Console.WriteLine(-1 >> 1); 正确的方法是: public static int RotateLeft(this int value, int count

(请注意,
int.MinValue
是111111111111-32 1s的二进制格式。)

这就是您想要做的吗

基本上你想要的是

(左)

(原始>(32位))

(右图)


(原始>>位)|(原始原始版本的移位不起作用。原因是,右移位有符号数将用符号位填充左位,而不是0

您可以通过以下方式验证此事实:

Console.WriteLine(-1 >> 1);
正确的方法是:

public static int RotateLeft(this int value, int count)
{
    uint val = (uint)value;
    return (int)((val << count) | (val >> (32 - count)));
}

public static int RotateRight(this int value, int count)
{
    uint val = (uint)value;
    return (int)((val >> count) | (val << (32 - count)));
}
public static int RotateLeft(此int值,int计数)
{
uint val=(uint)值;
返回值(int)((val>(32-计数));
}
公共静态int RotateRight(此int值,int计数)
{
uint val=(uint)值;

return(int)((val>>count)|(val注意,如果要创建对较短整数值进行操作的重载,则需要添加额外的步骤,如所示:

public static byte RotateLeft(
    this byte value,
    int count )
{
    // Unlike the RotateLeft( uint, int ) and RotateLeft( ulong, int ) 
    // overloads, we need to mask out the required bits of count 
    // manually, as the shift operaters will promote a byte to uint, 
    // and will not mask out the correct number of count bits.
    count &= 0x07;
    return (byte)((value << count) | (value >> (8 - count)));
}
公共静态字节RotateLeft(
这个字节值,
整数计数)
{
//与RotateLeft(uint,int)和RotateLeft(ulong,int)不同
//重载时,我们需要屏蔽所需的计数位
//手动,因为移位运算符将一个字节提升到uint,
//并且不会掩盖正确的计数位数。
计数&=0x07;
返回(字节)((值>8-计数));
}
32位和64位重载不需要掩蔽操作,因为移位运算符自己负责左手操作数大小的掩蔽操作。

使用最新的C#7,您现在可以通过ref扩展方法创建,这样您就可以摆脱不断存储将helper函数返回到变量中

// if you are using string

string str=Convert.ToString(number,2);

str=str.PadLeft(32,'0');




//Rotate right


str = str.PadLeft(33, str[str.Length - 1]);

str= str.Remove(str.Length - 1);

number=Convert.ToInt32(str,2);



//Rotate left


str = str.PadRight(33, str[0]);

str= str.Remove(0,1);

number=Convert.ToInt32(str,2);
这很好地简化了rotate函数,消除了一类常见的错误,即您忘记重新存储函数的返回值,但同时可能引入了一种全新的、完全不同的错误类型,即
ValueTypes
在您不希望或不期望的情况下,不经意地在原地修改

public static void Rol(ref this ulong ul) => ul = (ul << 1) | (ul >> 63);

public static void Rol(ref this ulong ul, int N) => ul = (ul << N) | (ul >> (64 - N));

public static void Ror(ref this ulong ul) => ul = (ul << 63) | (ul >> 1);

public static void Ror(ref this ulong ul, int N) => ul = (ul << (64 - N)) | (ul >> N);
///   note: ---^        ^---^--- extension method can now use 'ref' for ByRef semantics
这是每个对应呼叫站点的C代码。由于完全JIT优化的AMD64代码非常小,我也可以将其包括在这里。这是最佳情况:

static ulong x = 1;   // static so it won't be optimized away in this simple test

// ------- ByVal extension method; c̲a̲l̲l̲e̲r̲ must reassign 'x' with the result -------

                     x = x.Rol_ByVal();
// 00007FF969CC0481  mov         rax,qword ptr [7FF969BA4888h]  
// 00007FF969CC0487  rol         rax,1  
// 00007FF969CC048A  mov         qword ptr [7FF969BA4888h],rax  


// ------- New in C#7, ByRef extension method can directly alter 'x' in-situ -------

                     x.Rol_ByRef(); 
// 00007FF969CC0491  rol         qword ptr [7FF969BA4888h],1  
哇。是的,这可不是开玩笑。一下子我们就可以看出,ECMA CIL(.NET)中间语言中明显缺乏
操作码.Rot
-指令家族几乎没有问题;抖动能够看穿我们的一堆C#变通代码
(ul>63)
预测其基本意图,在这两种情况下,x64 JIT都通过简单地发出本机
rol
指令来实现。令人印象深刻的是,ByRef版本使用一条指令直接在主存目标地址上执行旋转,甚至不将其加载到寄存器中

在ByVal的情况下,您仍然可以看到多余复制的残留痕迹,这是在被调用方法完全优化之前保持调用方原始值不变所必需的(这是值类型语义的本质)。对于此处的整数旋转,它只是将目标整数额外提取/存储到64位寄存器
rax

为了澄清这一点,让我们在调试会话中重新抑制JIT优化。这样做将使我们的助手扩展方法返回,并提供完整的正文和堆栈框架来更好地解释上一段的第一句话。首先,让我们看看调用站点。这里我们可以看到传统的
ValueType
semanti的效果cs,这归结为确保没有较低的堆栈帧可以操作任何父帧的
ValueType
副本:

按值:

                     x = x.Rol_ByVal();
// 00007FF969CE049C  mov         rcx,qword ptr [7FF969BC4888h]  
// 00007FF969CE04A3  call        00007FF969CE00A8  
// 00007FF969CE04A8  mov         qword ptr [rbp-8],rax  
// 00007FF969CE04AC  mov         rcx,qword ptr [rbp-8]  
// 00007FF969CE04B0  mov         qword ptr [7FF969BC4888h],rcx  
                     x.Rol_ByRef();
// 00007FF969CE04B7  mov         rcx,7FF969BC4888h  
// 00007FF969CE04C1  call        00007FF969CE00B0
//             ...all done, nothing to do here; the callee did everything in-place for us

参考

                     x = x.Rol_ByVal();
// 00007FF969CE049C  mov         rcx,qword ptr [7FF969BC4888h]  
// 00007FF969CE04A3  call        00007FF969CE00A8  
// 00007FF969CE04A8  mov         qword ptr [rbp-8],rax  
// 00007FF969CE04AC  mov         rcx,qword ptr [rbp-8]  
// 00007FF969CE04B0  mov         qword ptr [7FF969BC4888h],rcx  
                     x.Rol_ByRef();
// 00007FF969CE04B7  mov         rcx,7FF969BC4888h  
// 00007FF969CE04C1  call        00007FF969CE00B0
//             ...all done, nothing to do here; the callee did everything in-place for us
正如我们从与这两个片段相关联的C#代码中所期望的那样,我们看到by val调用方在调用返回后有一系列工作要做。这是一个用完全独立的
ulong
值覆盖
ulong
值“x”的父副本的过程在
rax
寄存器中返回

现在让我们看看调用的目标函数的代码。查看它们需要强制JIT“抑制”优化。以下是x64版本JIT为
Rol\u ByVal
Rol\u ByRef
函数发出的本机代码

为了关注二者之间微小但至关重要的区别,我剥离了一些管理样板文件(我将堆栈框架设置和拆卸留给了上下文,并在本例中展示了如何在实际内容指令的基础上增加辅助内容)你能看到ByRef在工作中的间接作用吗?我指出了这一点很有帮助:-/

                 static ulong Rol_ByVal(this ulong ul) => (ul << 1) | (ul >> 63);
// 00007FF969CD0760  push        rbp  
// 00007FF969CD0761  sub         rsp,20h  
// 00007FF969CD0765  lea         rbp,[rsp+20h]  
// ...
// 00007FF969CE0E4C  mov         rax,qword ptr [rbp+10h]  
// 00007FF969CE0E50  rol         rax,1  
// 00007FF969CD0798  lea         rsp,[rbp]  
// 00007FF969CD079C  pop         rbp  
// 00007FF969CD079D  ret  

                 static void Rol_ByRef(ref this ulong ul) => ul = (ul << 1) | (ul >> 63);
// 00007FF969CD0760  push        rbp  
// 00007FF969CD0761  sub         rsp,20h  
// 00007FF969CD0765  lea         rbp,[rsp+20h]  
// ...
// 00007FF969CE0E8C  mov         rax,qword ptr [rbp+10h]  
// 00007FF969CE0E90  rol         qword ptr [rax],1              <--- !
// 00007FF969CD0798  lea         rsp,[rbp]  
// 00007FF969CD079C  pop         rbp  
// 00007FF969CD079D  ret  
静态ulong Rol_ByVal(此ulong ul)=>(ul>63);
//00007FF969CD0760推送rbp
//00007FF969CD0761子rsp,20小时
//00007FF969CD0765 lea rbp,[rsp+20小时]
// ...
//00007FF969CE0E4C mov rax,qword ptr[rbp+10h]
//00007FF969CE0E50 rol rax,1
//00007FF969CD0798 lea rsp,[rbp]
//00007FF969CD079C pop rbp
//00007FF969CD079D ret
静态无效Rol_ByRef(参考此ulong ul)=>ul=(ul>63);
//00007FF969CD0760推送rbp
//00007FF969CD0761子rsp,20小时
//00007FF969CD0765 lea rbp,[rsp+20小时]
// ...
//00007FF969CE0E8C mov rax,qword ptr[rbp+10h]

//00007FF969CE0E90 rol qword ptr[rax],1对于使用.NET Core 3.0或.NET 5.0及更高版本的用户,可以使用和。

@Mehrdad:是的,我刚意识到这一点。修复了否
                     x.Rol_ByRef();
// 00007FF969CE04B7  mov         rcx,7FF969BC4888h  
// 00007FF969CE04C1  call        00007FF969CE00B0
//             ...all done, nothing to do here; the callee did everything in-place for us
                 static ulong Rol_ByVal(this ulong ul) => (ul << 1) | (ul >> 63);
// 00007FF969CD0760  push        rbp  
// 00007FF969CD0761  sub         rsp,20h  
// 00007FF969CD0765  lea         rbp,[rsp+20h]  
// ...
// 00007FF969CE0E4C  mov         rax,qword ptr [rbp+10h]  
// 00007FF969CE0E50  rol         rax,1  
// 00007FF969CD0798  lea         rsp,[rbp]  
// 00007FF969CD079C  pop         rbp  
// 00007FF969CD079D  ret  

                 static void Rol_ByRef(ref this ulong ul) => ul = (ul << 1) | (ul >> 63);
// 00007FF969CD0760  push        rbp  
// 00007FF969CD0761  sub         rsp,20h  
// 00007FF969CD0765  lea         rbp,[rsp+20h]  
// ...
// 00007FF969CE0E8C  mov         rax,qword ptr [rbp+10h]  
// 00007FF969CE0E90  rol         qword ptr [rax],1              <--- !
// 00007FF969CD0798  lea         rsp,[rbp]  
// 00007FF969CD079C  pop         rbp  
// 00007FF969CD079D  ret