【问题标题】:Bitwise shifting vs size of operands (RHEL7 64 bit) [duplicate]按位移位与操作数大小(RHEL7 64 位)[重复]
【发布时间】:2021-06-18 04:11:22
【问题描述】:

所有,

long long unsigned int bigvalue;
bigvalue = (codeword[0] & 0XFFFC) >> 2;
bigvalue |= (codeword[1] & 0XFFFF) << 14;
bigvalue |= (codeword[2] & 0XFFFF) << 30;
bigvalue |= (codeword[3] & 0XFFFF) << 46;

codeword 是 guint16 类型。

最后一行出现错误:left shift count &gt;= width of type

缓解的方法是什么?

TIA!!

编辑:

有一个建议的答案。然而问题是完全不同的。我问的是编译器错误,而引用的问题是关于错误的结果。

EDIT2:

为了提供更多的上下文 - 这段代码假设解析 WS 流(它在解析器内部)。代码由 Perl 脚本根据规则集自动生成。我正在尝试解决由于最后一行不存在而导致代码崩溃的问题。

应该解析的字段是 68 位长,它被读入 5 个元素 - 码字 [i]。前面是 2 位指示符,因此第二行是 0xfffc。

我会尝试投射并在明天报告。

谢谢。

EDIT3:

请,请,请停止建议与此完全无关的问题作为解决方案!他们没有任何共同点!!

谢谢。

【问题讨论】:

标签: c bitwise-operators bit-shift


【解决方案1】:

对于像bigvalue |= (codeword[3] &amp; 0XFFFF) &lt;&lt; 46; 这样的表达式; C 将首先查看(codeword[3] &amp; 0XFFFF) 并将其提升为unsigned int(可能是32 位);然后它会尝试将这个中间 unsigned int 左移 46(并抱怨移位计数对于“可能的 32 位”无符号整数来说太大了)。

要解决此问题,您可以告诉 C 将中间值提​​升为更大的大小。例如:

    bigvalue |= (long long unsigned int)(codeword[3] & 0XFFFF) << 46;

请注意,您也可以使用0xFFFFULL 作为掩码;但是如果codeword[3] 已经是一个无符号的 16 位整数,那么掩码实际上不会做任何有用的事情并且可以被删除。例如:

    bigvalue |= (long long unsigned int)codeword[3] << 46;

【讨论】:

  • 我为这个问题提供了更多背景信息。代码是很久以前写的,但我认为很少经过测试,直到现在才使用这种特定场景。
  • codeword[3] 将被转换为unsigned int,而不是升级为unsigned int。促销是适用于单独考虑的单个值的特定转换,它们永远不会改变值。转换为unsigned int 以匹配0xFFFF通常的算术转换 的一部分,这些可能会更改值,就像将有符号类型转换为无符号时一样。
【解决方案2】:

我猜guint16 是 16 位宽度,那么它应该不能左移 30 位和 46 位,或者至少结果为零。

【讨论】:

  • 这是完全错误的,如果int 包含64 位,那么显然guint16 可以毫无问题地移动46。在大多数现代架构中,超过位宽的移位通常不会导致为零,因为只会考虑移位计数的低 6 位。在 C 中,这是未定义的行为
  • @phuclv 好像有误会:我猜guint16是16位宽度,而不是像int那样的64位宽度。
  • 当然我假设guint16 有16 位,但它会被提升为int,如果int 有64 位,那么不会发生什么特别的事情。 UB 仅在 int 少于 46 位时发生。 C 没有说具体的类型大小,int 只要求至少有 16 位
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-28
  • 1970-01-01
相关资源
最近更新 更多