【问题标题】:What happens when you bit shift beyond the end of a variable?当您在变量末尾进行位移时会发生什么?
【发布时间】:2010-12-01 23:41:18
【问题描述】:

如果你有一些变量(在堆栈上)并且你左移或右移超出了它的末尾会发生什么?

byte x = 1;
x >> N;

如果 x 是一个指向内存转换为字节的指针,而你做同样的事情呢?

byte* x = obtain pointer from somewhere;
*x = 1;
*x >> N;

【问题讨论】:

  • 反问:如果您希望该内存位置的位在下一个位置移动,接下来会发生什么?这是否意味着来自下一个存储位置的位将进一步移位?有了这个逻辑,所有的内存都会被转移。你不认为它必须停在某个地方吗?
  • 那么真正的问题是,在内存空间边缘的第一个和最后一个位会发生什么。 ;)
  • @jalf:至少有两个平行宇宙是没有问题的。

标签: c++ c bit-manipulation


【解决方案1】:

它不会(必然)变为零。行为未定义(C99 §6.5.7,“按位移位运算符”):

如果右操作数的值为 负或大于或等于 到提升的左​​侧的宽度 操作数,行为未定义。

(C++0x §5.8,“移位运算符”):

如果正确,则行为未定义 操作数为负数或大于 或等于位的长度 提升左操作数。

被移位的值的存储对此没有任何影响。

【讨论】:

  • 呃……“右操作数为负数”和“右操作数大于或等于提升的左操作数的宽度”都不是这种情况。 OP 没有指定 N 的值。我将问题读作“我认为这里的值无关紧要,因为 x 是 1”。
  • 重要提示:在这种情况下,width 表示CHAR_BIT * sizeof(var),而不是log2(var)
  • 多年来,我已经看到 N 大于或等于字长的两种行为。到目前为止,最常见的行为 1 是所有位“移出”并且结果为零。另一种行为是 N 以字长为模默默地减少。例如,此架构上的 x >> 32 只是 32 位类型 x 的空操作。
  • @GregS:其他行为是可能的(并且确实发生在现实世界中)。例如,对于 ARM 上的大多数编译器,可变移位量以 256 为模减少,然后饱和到 0-32 范围(这是硬件所做的;一些编译器发出额外的指令来获得不同的行为,但大多数编译器不会)。我还看到了其他几种行为。
【解决方案2】:

我认为您对位移的作用感到困惑。它们是算术运算符,相当于乘以或除以 2 的幂(以关于 C 如何处理负数的一些怪异为模)。 它们不会移动内存中的任何位。更改任何变量/内存内容的唯一方法是将表达式的结果分配回某处。

至于当移位运算符的右手操作数大于或等于左手表达式类型的宽度时会发生什么,行为未定义。

【讨论】:

    【解决方案3】:

    我认为你很困惑。 x >> y 实际上并没有改变 x。它计算一个新值。

    正如斯蒂芬所说,y 不能为负数,并且必须小于“提升的左操作数的宽度”(阅读类型提升)。但除此之外,“移到最后”的位会被简单地丢弃。 1 >> 2(请注意,2 不是负数,它小于用于表示 1 的位数,可能是 32,但肯定至少是 16)计算结果为 0。

    【讨论】:

      猜你喜欢
      • 2016-09-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 2014-12-19
      • 2015-09-14
      • 2012-12-03
      相关资源
      最近更新 更多