热门标签 | 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。


推荐阅读
  • 本文介绍了一个项目中如何在Windows平台上实现多声道音频数据的采集,特别是针对DANTE音频接口的8路立体声音频通道。文章详细描述了使用Windows底层音频API进行音频采集的方法,并提供了一个具体的实现示例。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
  • 软件工程课堂测试2
    要做一个简单的保存网页界面,首先用jsp写出保存界面,本次界面比较简单,首先是三个提示语,后面是三个输入框,然 ... [详细]
  • 在寻找轻量级Ruby Web框架的过程中,您可能会遇到Sinatra和Ramaze。两者都以简洁、轻便著称,但它们之间存在一些关键区别。本文将探讨这些差异,并提供详细的分析,帮助您做出最佳选择。 ... [详细]
  • 本文介绍了一个经典的算法问题——活动选择问题,来源于牛客网的比赛题目。该问题要求从一系列活动集合中选出最多数量的相容活动,确保这些活动的时间段不重叠。 ... [详细]
  • 本文探讨了如何使用pg-promise库在PostgreSQL中高效地批量插入多条记录,包括通过事务和单一查询两种方法。 ... [详细]
  • 深入解析RDMA中的队列对(Queue Pair)
    本文将详细探讨RDMA架构中的关键组件——队列对(Queue Pair,简称QP),包括其基本概念、硬件与软件实现、QPC的作用、QPN的分配机制以及用户接口和状态机。通过这些内容,读者可以更全面地理解QP在RDMA通信中的重要性和工作原理。 ... [详细]
  • 深入理解 JMeter 定时器
    本文详细介绍了JMeter中定时器的功能和使用方法,探讨了其在性能测试中的重要性,并结合实际案例解释了如何合理配置定时器以模拟真实的用户行为。文章还涵盖了定时器的执行顺序及其与其他元件的相互作用。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • NVIDIA Titan RTX深度评测
    NVIDIA的Titan RTX被誉为当前最强大的桌面显卡之一,其卓越的性能和高昂的价格吸引了众多专业人士和技术爱好者的关注。本文将详细介绍Titan RTX的技术规格、性能表现及应用场景。 ... [详细]
  • 本文详细解析了2019年西安邀请赛中的一道树形动态规划题目——J题《And And And》。题目要求计算树中所有子路径异或值为0的集合数量,通过深入分析和算法优化,提供了高效的解决方案。 ... [详细]
  • 本文详细介绍了Linux内核中misc设备驱动框架的实现原理及应用方法,包括misc设备的基本概念、驱动框架的初始化过程、数据结构分析以及设备的注册与注销流程。 ... [详细]
  • 管理类联考英语复习指南:基础语法(八)
    本文探讨了谓语动词和分词在句子中的作用,包括分词作为状语、定语和宾语补足语的使用方法,以及分词的时态和语态变化。 ... [详细]
  • 本文探讨了如何在Android应用中实现图片的保存至外部存储,并通过原生方式分享这些图片。主要介绍了保存图片的不同策略以及通过Intent进行文件分享的具体步骤。 ... [详细]
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社区 版权所有