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


推荐阅读
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 解决PHP与MySQL连接时出现500错误的方法
    本文详细探讨了当使用PHP连接MySQL数据库时遇到500内部服务器错误的多种解决方案,提供了详尽的操作步骤和专业建议。无论是初学者还是有经验的开发者,都能从中受益。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文深入探讨了C++对象模型中的一些细节问题,特别是虚拟继承和析构函数的处理。通过具体代码示例和详细分析,揭示了书中某些观点的不足之处,并提供了更合理的解释。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 火星商店问题:线段树分治与持久化Trie树的应用
    本题涉及编号为1至n的火星商店,每个商店有一个永久商品价值v。操作包括每天在指定商店增加一个新商品,以及查询某段时间内某些商店中所有商品(含永久商品)与给定密码值的最大异或结果。通过线段树分治和持久化Trie树来高效解决此问题。 ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • 本文讨论了如何根据特定条件动态显示或隐藏文件上传控件中的默认文本(如“未选择文件”)。通过结合CSS和JavaScript,可以实现更灵活的用户界面。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 基因组浏览器中的Wig格式解析
    本文详细介绍了Wiggle(Wig)格式及其在基因组浏览器中的应用,涵盖variableStep和fixedStep两种主要格式的特点、适用场景及具体使用方法。同时,还提供了关于数据值和自定义参数的补充信息。 ... [详细]
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社区 版权所有