【问题标题】:Why would a 32 bit shift in C# return the value it was originally shifting?为什么 C# 中的 32 位移位会返回它最初移位的值?
【发布时间】:2021-02-09 08:32:50
【问题描述】:

我只是想澄清一下 C# 位移。

当我将 UINT32 的位向右移动 32 位时,我将值移回。我的预期结果是将值归零00000000

例如:

System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFFFF", 16) >> 8).ToString("X8"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFFFF", 16) >> 16).ToString("X8"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFFFF", 16) >> 24).ToString("X8"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFFFF", 16) >> 32).ToString("X8"));

System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FF", 16) >> 8).ToString("X"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFF", 16) >> 16).ToString("X"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFF", 16) >> 24).ToString("X"));
System.Diagnostics.Debug.WriteLine((Convert.ToUInt32("FFFFFFFF", 16) >> 32).ToString("X"));

生产

00FFFFFF
0000FFFF
000000FF
FFFFFFFF

0
0
0
FFFFFFFF

有人能解释一下为什么会这样吗?

【问题讨论】:

  • 在 C 和 C++ 中,行为是未定义的,允许编译器选择最快的指令。在 C# 中,行为被定义为lhs >> (0x1f & rhs) 以给出确定性。
  • 啊,这就是我所追求的。我真的很想知道为什么。这就说得通了。请张贴作为答案,因为这是我所追求的信息。

标签: c# operators bit-shift


【解决方案1】:

这是一种预期且记录在案的行为 - 当计数为 32 移位时(对于 int/uint)实际上是 0 移位,因为只考虑了 5 个低位(32 & 0x1f 为 0):

Bitwise and shift operators (C# reference): Shift count of the shift operators

如果 x 的类型是 int 或 uint,则移位计数由右手操作数的低五位定义。也就是说,移位计数是根据 count & 0x1F(或 count & 0b_1_1111)计算得出的。


根据评论,您的实际问题似乎是“为什么 C# 设计人员决定以这种方式定义它,而不是其他一些或更好但坚持类似于 C/C++ 的未定义行为”,这实际上是基于意见的(除非有一些存在保存特定讨论和决定的官方设计文档):

虽然 UB 可能允许对生成的代码进行一些额外的优化或简化编译器,但它也会导致代码在与不同的编译器一起使用时可能会完全改变其行为。一般来说,您可能会发现 C# 和 .Net 更倾向于万无一失的正确性,而不是潜在的性能提升。另一方面,C/C++ 更多地依赖于对语言边界有深刻理解的开发人员来生成在所有编译器上运行相同的代码。

至于为什么选择特定行为 - 使用哪个特定选择来定义行为并不重要,因为不同的编译器/处理器对于任何特定的未定义行为都有不同的首选结果。

额外的考虑是易于记录 - 例如“如果第 16 位为 0,则移位超过 31(有符号)和 32(无符号)产生 01 重复 16 次,否则为有符号减一,无符号为零,除非count 大于 42,那么……”

【讨论】:

  • 感谢您提供的信息,我想知道为什么会这样。我之前确实找到了这个文档,我应该把它放在我原来的帖子里。
  • 哇,感谢您提供的信息,是的,您是对的,我可以看到我的问题可以通过一些调整来获得答案。感谢您花时间根据对我的问题的新认识来改进您的答案。真的很感激。
猜你喜欢
  • 2010-12-01
  • 2011-02-08
  • 2013-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多