什么是按位移位(bit-shift)运算符以及它们如何工作?

2024-01-20

我一直在业余时间尝试学习 C,其他语言(C#、Java 等)也有相同的概念(并且通常有相同的运算符)...

在核心层面,位移位(<<, >>, >>>),它可以帮助解决什么问题,以及隐藏在弯道周围的陷阱是什么?换句话说,这是一本关于位移位所有优点的绝对初学者指南。


移位运算符的作用正如其名称所暗示的那样。他们移位。以下是对不同移位运算符的简要(或不那么简要)介绍。

运营商

  • >>是算术(或有符号)右移运算符。
  • >>>是逻辑(或无符号)右移运算符。
  • <<是左移运算符,满足逻辑移位和算术移位的需要。

所有这些运算符都可以应用于整数值(int, long, 可能short and byte or char)。在某些语言中,将移位运算符应用于小于的任何数据类型int自动调整操作数的大小int.

注意<<<不是运算符,因为它是多余的。

另请注意C 和 C++ 不区分右移运算符。他们只提供>>运算符,右移行为是为有符号类型定义的实现。答案的其余部分使用 C# / Java 运算符。

(在所有主流 C 和 C++ 实现中,包括 GCC 和 Clang/LLVM,>>有符号类型上是算术。某些代码假设了这一点,但这不是标准所保证的。它不是不明确的, 尽管;该标准需要实现以一种或另一种方式定义它。但是,负符号数左移is未定义的行为(有符号整数溢出)。因此,除非您需要算术右移,否则通常最好使用无符号类型进行位移位。)


左移 (

整数作为一系列位存储在内存中。例如,数字 6 存储为 32 位int将会:

00000000 00000000 00000000 00000110

将此位模式向左移动一位(6 << 1) 将得到数字 12:

00000000 00000000 00000000 00001100

正如您所看到的,数字已向左移动了一位,右侧的最后一位数字用零填充。您可能还注意到,左移相当于乘以 2 的幂。所以6 << 1相当于6 * 2, and 6 << 3相当于6 * 8。一个好的优化编译器会尽可能用移位代替乘法。

非循环变速

请注意,这些是not循环移位。将该值向左移动一位(3,758,096,384 << 1):

11100000 00000000 00000000 00000000

结果为 3,221,225,472:

11000000 00000000 00000000 00000000

“偏离末尾”的数字将丢失。它不会环绕。


逻辑右移 (>>>)

逻辑右移与左移相反。它们不是向左移动位,而是向右移动。例如,移动数字 12:

00000000 00000000 00000000 00001100

向右移动一个位置(12 >>> 1) 将取回我们原来的 6:

00000000 00000000 00000000 00000110

所以我们看到向右移动相当于除以 2 的幂。

丢失的位消失了

然而,移位不能收回“丢失”的位。例如,如果我们改变这种模式:

00111000 00000000 00000000 00000110

向左 4 个位置(939,524,102 << 4),我们得到 2,147,483,744:

10000000 00000000 00000000 01100000

然后向后移动((939,524,102 << 4) >>> 4)我们得到 134,217,734:

00001000 00000000 00000000 00000110

一旦丢失了比特,我们就无法恢复原来的值。


算术右移 (>>)

算术右移与逻辑右移完全相同,只不过它不是用零填充,而是用最高有效位填充。这是因为最高有效位是sign位,或区分正数和负数的位。通过用最高有效位填充,算术右移可以保留符号。

例如,如果我们将此位模式解释为负数:

10000000 00000000 00000000 01100000

我们有数字-2,147,483,552。通过算术移位 (-2,147,483,552 >> 4) 将其向右移动 4 个位置将得到:

11111000 00000000 00000000 00000110

或数字-134,217,722。

所以我们看到,我们通过使用算术右移而不是逻辑右移保留了负数的符号。我们再一次看到我们正在执行 2 的幂除法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是按位移位(bit-shift)运算符以及它们如何工作? 的相关文章

  • 由于 play-services-base-17.1.0.aar 转换错误,无法构建项目

    所以基本上我已经快一年没有打开我的 Android Studio 项目了 这次是打开和构建它的时候了 更新 Android Studio 和项目的所有插件后 我终于遇到了这个错误 Execution failed for task app
  • java8 Collectors.toMap() 限制?

    我正在尝试使用java8Collectors toMap on a Stream of ZipEntry 这可能不是最好的想法 因为在处理过程中可能会发生异常 但我想这应该是可能的 我现在收到一个我不明白的编译错误 我猜是类型推理引擎 这是
  • Excel 2013 数据透视表不会更改当前页面,除非手动导航到

    我们有一小段 VBA 代码 多年来一直完美运行 本质上是 Me PivotTables APivot PivotFields AField CurrentPage Some text 这种方法一直有效 直到 Excel 2013 该行将失败
  • 如何从 Magento One Page Checkout 获取发布数据?

    为了在 Magento Checkout 中添加客户评论字段 我在相应的模板文件中添加了一个文本字段 并使用如下观察器将评论添加到订单中 comment strip tags Mage app gt getRequest gt getPar
  • 如何在 iOS 中注册自定义文件类型

    我目前正在创建一个应用程序 我想让用户在其中备份他们的文件 plist m4a 我压缩文件并将扩展名更改为自定义扩展名 专门针对我的应用程序 例如 MyBackup 然后 用户可以通过电子邮件或 iTunes 文件共享进行导出 我已经阅读过
  • javax.persistence.Table.indexes()[Ljavax/persistence/Index 中的 NoSuchMethodError

    我有一个 Play Framework 应用程序 并且我was使用 Hibernate 4 2 5 Final 通过 Maven 依赖项管理器检索 我决定升级到 Hibernate 4 3 0 Final 成功重新编译我的应用程序并运行它
  • 如何更改 aptana studio 的背景颜色?

    如何将 Aptana IDE 或整个主题 的黑色背景更改为其他背景 例如蓝色 正如 gyozo 在评论中提到的 对于蓝色主题 请使用 窗口 gt 首选项 gt Aptana Studio gt 主题 并选择 Eclipse 主题
  • 如何获得 JavaScript 阶乘程序的循环来显示所使用的工作?

    你好 我面临着用 JavaScript 编写一个程序的挑战 尽管我对它不太了解 但它要求用户输入一个数字 然后计算该数字的阶乘 我使用了已经提出的问题并设法使计算正常工作 但无法获得所需的输出 我必须在以下输出中获取它 而不使用任何花哨的库
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str
  • 在Python中停止ThreadPool中的进程

    我一直在尝试为控制某些硬件的库编写一个交互式包装器 用于 ipython 有些调用对 IO 的影响很大 因此并行执行任务是有意义的 使用 ThreadPool 几乎 效果很好 from multiprocessing pool import
  • Jackson 将单个项目反序列化到列表中

    我正在尝试使用一项服务 该服务为我提供了一个带有数组字段的实体 id 23233 items name item 1 name item 2 但是 当数组包含单个项目时 将返回该项目本身 而不是包含一个元素的数组 id 43567 item
  • Swagger/Openapi-Annotations:如何使用 $ref 生成 allOf?

    我正在生成 Rest 端点 包括添加OpenAPI Swagger对生成的代码进行注释 虽然它对于基本类型运行得很好 但我在自定义类方面遇到了一些问题 现在我有很多自定义类的重复架构条目 使用 Schema 实现 MyClass class
  • 不区分大小写的字符串比较 C++ [重复]

    这个问题在这里已经有答案了 我知道有一些方法可以进行忽略大小写的比较 其中涉及遍历字符串或一个good one https stackoverflow com questions 11635 case insensitive string
  • Biopython 可以执行 Seq.find() 来解释歧义代码吗

    我希望能够在 Seq 对象中搜索考虑歧义代码的子序列 Seq 对象 例如 以下内容应该是正确的 from Bio Seq import Seq from Bio Alphabet IUPAC import IUPACAmbiguousDNA
  • 使用 VBA 通过 Access 导航网页/操作 IE

    你好 StackOverflow 社区 我有一个关于使用 Access VBA 操作 IE 的问题 本质上 我正在尝试编写代码 使用 IE 打开特定网页 在该页面中搜索特定链接 目标链接的名称将取决于用户的情况 通过以编程方式单击该链接导航
  • 我可以让 swagger-php 在查询字符串上使用数组吗?

    我使用 Swagger php 当我定义查询字符串上的参数时 它可以是一个数组 但据我所知 它不支持这种查询字符串 https api domain tld v1 objects q 1 q 5 q 12 我相信这会被设定in the co
  • 使用适用于 Android 和 ios 的 Angular NativeScript 的透明选项卡栏和操作栏

    我想让标签栏透明 操作栏在滑动布局或页面上透明 操作栏或选项卡栏必须位于页面顶部 就像两层一样 我尝试过使用 css 使其透明 但它在页面上并没有变得透明
  • JQuery 删除和内存泄漏

    我正在开发一个游戏 我看到了很多内存消耗 我使用jquery animate 动画完成后 我 remove 元素 我的问题是 从 dom 树中删除一个元素后 对象还存在记忆中吗 Javascript 是一种垃圾收集语言 这意味着当没有代码保
  • 使用 IIS 发布:找不到服务器 DNS

    我正在尝试使用 IIS 发布我的项目 我能够通过 Visual Studio 发布它 La aplicaci n web se public correctamente file D www plataformafantasy com Co
  • 在 Google 地图上绘制线条/路径

    我很长一段时间都在忙于寻找如何在 HelloMapView 中的地图上的两个 GPS 点之间画一条线 但没有运气 谁能告诉我该怎么做 假设我使用扩展 MapView 的 HelloMapView 我需要使用叠加层吗 如果是这样 我是否必须重

随机推荐