【问题标题】:Bit shifting an int 32 times in C在 C 中将 int 位移 32 次
【发布时间】:2012-08-27 16:13:55
【问题描述】:

我有一个特定的 C 位移场景,我认为 Stack Overflow 尚未涵盖该场景。 (如果是,我还没找到!)

本练习使用signed ints 作为数据类型。

取值0x80000000(最高有效位中只有一个 1。)

在机器上使用算术右移将其右移一次(我的就是这样做的)。

结果 = 0xC0000000(最左边的字节为 1100 0000)。

继续移动它,你应该从左到右填充一个。

结果 = 0xFFFFFFFF(全为。)

但是:尝试相同的示例,但移动一个额外的位置,全部一起:

0x80000000 >> 0x00000020(右移32次)

你的结果?我不知道。我的结果不是全部。事实上,我得到了0x00000001,这不是我想要的行为。为什么是这样?它是特定于机器的吗?

(背景:家庭作业将我的操作限制为几个位运算符来解决难题。这是难题的一个方面,但远非整个问题。)

【问题讨论】:

  • 上天禁止在 Stack Overflow 上覆盖每一天的每一个“位移场景”。我们可以帮助您理解 C,但我当然希望我们不必详细说明所有可能的类似问题。
  • 对不起,如果这不是一个合适的问题,我会删除它。你能解释一下为什么这个问题是个问题吗?
  • 右移只取 1 并右移不克隆它,所以在移一次 0x1000000 >> 1 后,你得到 0x0100000
  • @Rami,实际上这取决于值是有符号还是无符号
  • 别担心,我只是被听起来像是希望最终对 SO 上的每一种位移类型都有一个问题的想法逗乐了。这个问题很好,虽然它肯定是许多重复的问题之一,而且答案应该在任何好的 C++ 教科书中。

标签: c bit-shift


【解决方案1】:

这是未定义的行为

Why doesn't left bit-shift, "<<", for 32-bit integers work as expected when used more than 32 times?

这意味着您应该像避免瘟疫一样避免它。这里有一些链接,包括“每个 C 程序员应该知道的关于未定义行为的知识”:http://lwn.net/Articles/511767/

【讨论】:

  • 嘿,谢谢。我主要是一名 Java/C# 程序员,不习惯“未定义的行为”。我在一个月内收到了几本 C 编程书籍(生日礼物!),但还没有掌握 C/C++ 的心态。这些文章看起来很有希望。
【解决方案2】:

按操作数的位数移位具有未定义的行为,这就是您得到“意外”结果的原因。

【讨论】:

  • 我意识到这是一种愚蠢的情况,在真正的编程环境中,有些事情是要避免的,但是有没有办法知道这里内部发生​​了什么?
  • 这可以通过反汇编和gdb轻松分析,但我不会花时间在上面;)
  • 如果你想要机器特定的答案,发生的事情是 CPU 移位指令只查看移位值的低 5 位,而忽略高位。
  • @sourcejedi 就是我要找的!你确定吗?
  • @BlackVegetable "各种 CPU 上的底层移位操作对此做了不同的事情:例如,X86 将 32 位移位量截断为 5 位(因此 32 位移位与移位相同)按 0 位)” blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
【解决方案3】:

这是来自 C99 标准的引用:

6.5.7 移位运算符 [...]

3 [...] 如果右操作数的值为负数或 大于或等于提升的宽度 左操作数,行为未定义。

感谢original source

【讨论】:

  • Drat,真的没有办法知道,是吗?
  • 不是没有阅读标准或一本好的 C/C++ 书籍,没有。虽然,询问 SO 确实经常会产生一些好的答案!
【解决方案4】:

您不能移动超过其宽度的值。一个 int 数的 with 是多少?好吧,在 32 位系统中,它是 32 位的。如果您尝试在 gcc 中移动超过 32 的 int,则会收到以下警告:

warning: right shift count >= width of type [enabled by default]

如果您想获得0xFFFFFFFF,则必须转换 31 次,而不是 32 次。想想吧!

【讨论】:

  • 你被允许移动一个超过它的宽度的值,而 GCC 只给出一个警告。问题不在于那个。
  • 不,我明白。我试图解决这个难题的确切方法涉及位移 32 次,但现在我发现这完全是个坏主意。即使在一个愚蠢的学术解谜环境中。
  • @AndrejsCainikovs 是的,这是允许的,我们可以看到它只是发出警告。但是将其移动超过 32 位是否有意义?
  • 是的,如果你在做数学计算,这很有意义。不幸的是,由于这个和其他未定义的行为根本原因,需要实施变通方法并经常以不直接的方式进行计算。
猜你喜欢
  • 1970-01-01
  • 2013-09-18
  • 2010-11-16
  • 2014-04-24
  • 2010-10-31
  • 1970-01-01
  • 2015-08-03
  • 1970-01-01
  • 2011-08-14
相关资源
最近更新 更多