如果在移位运算符中使用强制转换运算符怎么办

如何解决如果在移位运算符中使用强制转换运算符怎么办

JLS

shift表达式的类型是左手的提升类型 操作数。

如果左侧操作数的提升类型为int,则仅 右侧操作数的五个最低位用作移位 距离。好像右手操作数受到了 掩码值为0x1f的按位逻辑AND运算符&(§15.22.1) (0b11111)。因此,实际使用的换档距离始终在 范围为0到31(含)。

如果左侧操作数的提升类型很长,则仅 右操作数的最低6位用作移位 距离。好像右手操作数受到了 掩码值为0x3f的按位逻辑AND运算符&(§15.22.1) (0b111111)。因此,实际使用的移动距离始终为 范围为0到63(含)。

因此,如果我使用(byte)100<<100(short)100<<100之类的转换运算符显式地创建一个字节和一个短操作数,那么正确的操作数的可用位是什么?

编辑:如果操作数已经使用强制转换运算符转换为其他(较小的)类型,则该操作数是否会进行数值提升(一元/二进制)?如果是这种情况,您将如何解释具有字节变量b1 = (byte)(b2 + b3)的表达式,因为在进行强制转换之后,字节结果可能会按照数字提升转换为int?

解决方法

Java 8 JLS also states in §5.6.1

5.6.1。一元数值促销

某些运算符将一元数值提升应用于单个操作数,该运算数必须产生数字类型的值:

...

  • 否则,如果操作数是编译时类型byteshortchar,则通过扩展原语将其提升为类型int的值转换(第5.1.2节)。

...

因此,如果我们采用以下表达式:

int i = ...
short s = (short) i << 2;

将导致编译器错误:

Main.java:4: error: incompatible types: possible lossy conversion from int to short
short s = (short) i << 2;

Ideone demo

这是由于强制转换绑定到shift的第一个参数,而不是整个表达式。这是带有显式括号的整个表达式:

short s = ((byte) i) << 2;

int i = ...;
int j = (short) i << 2;

将成功编译。

Ideone demo

因此,< int的有效位与int5位)相同,因为它们会自动上载到int

如果将整个表达式的结果强制转换为,例如shortshort s = (short) (i << 2),那么编译器中就不会发生自动操作。但是Bohemian's answer给出了逻辑运算符,确定了右运算符的哪些位将有效地影响运算符之后的值。演员。


在较新的JLS版本中,该部分已改写。例如,在Java 14 JLS,§5.6中我们发现(为简洁起见,本节已缩短,我建议阅读整个段落以获取完整的上下文):

5.6。数值上下文

数值上下文适用于算术运算符,数组创建和访问表达式,条件表达式以及切换表达式的结果表达式的操作数。

如果表达式是下列之一,则表达式将出现在数字算术上下文中:

...

  • 移位运算符<<>>>>>的操作数(第15.19节)。这些移位运算符的操作数将被单独对待而不是作为一个整体来对待。 long移位距离(右操作数)不会促进将值(左操作数)移位到long

...

数字提升确定数字上下文中所有表达式的提升类型。选择提升类型,以便可以将每个表达式转换为提升类型,并且在算术运算的情况下,将为提升类型的值定义该运算。在数字上下文中,表达式的顺序对于数字提升并不重要。规则如下:

...

  1. 接下来,根据以下规则,将扩展原语转换(第5.1.2节)和缩小原语转换(第5.1.3节)应用于某些表达式:

    ...

    • 否则,所有表达式都不属于doublefloatlong类型。在这种情况下,上下文的类型决定了如何选择提升的类型。

      在数值算术上下文或数值数组上下文中,提升后的类型为int,所有非int类型的表达式都将原语转换为int

      在数字选择上下文中,适用以下规则:

      ...

      • 否则,升级后的类型为int,所有非int类型的表达式都将原语转换为int

      ...

,

最大可用移位距离的位数由log 2 n给出,其中n是用于表示左手类型的值的位数。

byte有8位。 log 2 8是3。因此,仅使用最右边的3位,给出的移位值为0-7。

short具有16位。 log 2 16是4。所以仅使用最右边的4位,给出的移位值为0-15。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-