热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

带符号整数的算术位移。-Arithmeticbit-shiftonasignedinteger

Iamtryingtofigureouthowexactlyarithmeticbit-shiftoperatorsworkinC,andhowitwillaffe

I am trying to figure out how exactly arithmetic bit-shift operators work in C, and how it will affect signed 32-bit integers.

我正在试图弄清楚算术位移位操作符在C中是如何工作的,以及它将如何影响已签名的32位整数。

To make things simple, let's say we work within one byte (8 bits):

为了简单起见,假设我们在一个字节(8比特)内工作:

x = 1101.0101
MSB[ 1101.0101 ]LSB

Reading other posts on Stack Overflow and some websites, I found that: << will shift toward MSB (to the left, in my case), and fill "empty" LSB bits with 0s.

在Stack Overflow和一些网站上阅读其他文章,我发现:<<将向msb移动(在我的情况下),并填充“空”lsb位与0。

And >> will shift toward LSB (to the right, in my case) and fill "empty" bits with MS bit

>>将向LSB(在我的情况下)向右移动,并将“空”位填充到MS比特。

So, x = x <<7 will result in moving LSB to MSB, and setting everything to 0s.

因此,x = x <<7将会使LSB移动到MSB,并将一切设置为0。

1000.0000

Now, let's say I would >> 7, last result. This would result in [0000.0010]? Am I right?

现在,假设我要>> 7,最后一个结果。这将导致[0000.0010]?我说的对吗?

Am I right about my assumptions about shift operators?

我对移动运营商的假设是否正确?

I just tested on my machine, **

我刚在我的机器上测试过。

int x = 1;   //000000000......01

x = x <<31; //100000000......00

x = x >> 31; //111111111......11 (Everything is filled with 1s !!!!!) 

Why?

为什么?

4 个解决方案

#1


47  

Right shift of a negative signed number has implementation-defined behaviour.

负签名数的右移具有实现定义的行为。

If your 8 bits are meant to represent a signed 8 bit value (as you're talking about a "signed 32 bit integer" before switching to 8 bit examples) then you have a negative number. Shifting it right may fill "empty" bits with the original MSB (i.e. perform sign extension) or it may shift in zeroes, depending on platform and/or compiler.

如果你的8位代表一个有符号的8位值(在切换到8位示例之前,你正在讨论一个“有符号的32位整数”),那么你就有一个负数。将其右移可能会填满“空”位与原始的MSB(即执行符号扩展),或者它可以在零中移动,这取决于平台和/或编译器。

(Implementation-defined behaviour means that the compiler will do something sensible, but in a platform-dependent manner; the compiler documentation is supposed to tell you what.)

(实现定义的行为意味着编译器会做一些有意义的事情,但是是以平台依赖的方式;编译器文档应该告诉你什么。


A left shift, if the number either starts out negative, or the shift operation would shift a 1 either to or beyond the sign bit, has undefined behaviour (as do most operations on signed values which cause an overflow).

一个左移,如果这个数字开始是负数,或者移位操作会将一个1移动到符号位或者超过符号位,就会有未定义的行为(对于导致溢出的符号值的大多数操作也是如此)。

(Undefined behaviour means that anything at all could happen.)

(未定义的行为意味着任何事情都可能发生。)


The same operations on unsigned values are well-defined in both cases: the "empty" bits will be filled with 0.

在两种情况下,对未签名值的相同操作都是定义良好的:“空”位将填充为0。

#2


32  

Bitwise shift operations are not defined for negative values

位移位操作不是为负值定义的。

for '<<'

“<<”

6.5.7/4 [...] If E1 has a signed type and nonnegative value, and E1×2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.

6.5.7/4[…)如果E1签署类型和非负价值,在结果和E1×2 e2表示的类型,那么得到的值;否则,行为是未定义的。

and for '>>'

和“> >”

6.5.7/5 [...] If E1 has a signed type and a negative value, the resulting value is implementation- defined.

6.5.7/5[…]如果E1有一个符号类型和一个负值,则生成的值是实现定义的。

It's a waste of time to study the behaviour of these operations on signed numbers on a specific implementation, because you have no guarantee it will work the same way on any other implementation (an implementation is, for example, you compiler on your computer with your specific commad-line parameters).

研究这些操作在特定实现上的签名数字的行为是浪费时间,因为您不能保证它在任何其他实现上的工作方式都是相同的(例如,您的计算机上的编译器会使用特定的逗号行参数)。

It might not even work for an older or a newer version of the very same compiler. The compiler might even define those bits as random or undefined. This would mean that the very same code sequence could produce totally different results when used across your sources or even depend on things like assembly optimisation or other register usage. If encapsulated in a function it might not even produce the same result in those bits on two consecutive calls with the same arguments.

它甚至可能不会为更老的版本或同一编译器的新版本工作。编译器甚至可以将这些位定义为随机的或未定义的。这意味着,当使用不同的源代码时,相同的代码序列可能产生完全不同的结果,甚至依赖于诸如组装优化或其他寄存器使用之类的东西。如果封装在一个函数中,它甚至可能不会在两个连续调用相同参数的情况下产生相同的结果。

Considering only non-negative values, the effect of left shifting by 1 (expression <<1) is the same as multpliying the expression by 2 (provided expression * 2 does not overflow) and the effect of right shifting by 1 (expression >> 1) is the same as dividing by 2.

仅考虑非负值的值,左移1(表达式<<1)的效果与2(提供的表达式* 2不溢出)和右移1(表达式>> 1)的效果相同,即除以2。

#3


5  

As others said shift of negative value is implementation-defined.

正如其他人所说的,负值的转移是由实现定义的。

Most of implementations treat signed right shift as floor(x/2N) by filling shifted in bits using sign bit. It is very convenient in practice, as this operation is so common. On the other hand if you will shift right unsigned integer, shifted in bits will be zeroed.

大多数实现将签名的右移作为层(x/2N),用符号位填充移位。这在实践中非常方便,因为这个操作非常普遍。另一方面,如果你转换右无符号整数,移位的位将是零。

Looking from machine side, most implementations have two types of shift-right instructions:

从机器的角度来看,大多数实现都有两种类型的转换正确的指令:

  1. An 'arithmetic' shift right (often having mnemonic ASR or SRA) which works as me explained.

    一种“算术”的右移(通常有助记符ASR或SRA),正如我所解释的那样。

  2. A 'logic' shift right (oftem having mnemonic LSR or SRL or SR) which works as you expect.

    一个“逻辑”的右移(oftem有助记符LSR或SRL或SR),这是你所期望的。

Most of compilers utilize first for signed types and second for unsigned ones. Just for convenience.

大多数编译器首先使用已签名的类型,其次使用未签名的类型。只是为了方便。

#4


0  

In the 32 bit compiler

在32位编译器中。

x = x >> 31;

x = x >> 31;

here x is the signed integer so 32nd bit is sign bit.

这里x是有符号整数,所以32位是符号位。

final x value is 100000...000. and 32nd bit indicate -ive value.

最后的x值是100000…000。第32位表示-ive值。

here x value implement to 1's compliment.

这里x值执行到1的恭维。

then final x is -32768

最后x是-32768。


推荐阅读
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • ImmutableX Poised to Pioneer Web3 Gaming Revolution
    ImmutableX is set to spearhead the evolution of Web3 gaming, with its innovative technologies and strategic partnerships driving significant advancements in the industry. ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文详细介绍了Java中org.w3c.dom.Text类的splitText()方法,通过多个代码示例展示了其实际应用。该方法用于将文本节点在指定位置拆分为两个节点,并保持在文档树中。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 本文详细介绍了 com.facebook.drawee.view.SimpleDraweeView 中的 setScaleType 方法,提供了多个实际代码示例,并解释了其在不同场景下的应用。 ... [详细]
  • libsodium 1.0.15 发布:引入重大不兼容更新
    最新发布的 libsodium 1.0.15 版本带来了若干不兼容的变更,其中包括默认密码散列算法的更改和其他重要调整。 ... [详细]
  • ASP.NET MVC中Area机制的实现与优化
    本文探讨了在ASP.NET MVC框架中,如何通过Area机制有效地组织和管理大规模应用程序的不同功能模块。通过合理的文件夹结构和命名规则,开发人员可以更高效地管理和扩展项目。 ... [详细]
  • 本文详细介绍了 JavaScript 中的条件判断(if-else 和 switch)以及循环控制(for、while 和 do-while)。我们将探讨这些结构的基本语法、使用场景及注意事项,并补充一些实用技巧。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
author-avatar
dmcm0005
这个家伙很懒,什么也没留下!
Tags | 热门标签
RankList | 热门文章
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有