传送门

传送门2

以下copy:

int i = 0;
  i += ((b[0] & 0xff) << 24);
  i += ((b[1] & 0xff) << 16);
  i += ((b[2] & 0xff) << 8);
  i += ((b[3] & 0xff));

想必大家对这样的代码并不陌生,明白就可以不看了,想了解的继续往下看,不好的地方还请多多包涵!
个人经常看到这样的写法但是不明白为何,所以忽然想了解下于是研究了下.

有一定的计算机2进制计算基础的就可以看明白,如果不明白2进制,先去看看计算机2进制计算及转换之类的东西

===========开始...

原码,反码,补码概念
+1原 = 0000 0001
-1原  = 1000 0001
反码
正数的反码是其本身
负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.
补码
正数的补码就是其本身
负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

一部分int转byte
Java采用[补码]存储整数 int型为4字节 32位,byte为1字节8位
所以byte[]数组中存储一个int类型肯定是4个1字节的byte组成,即byte[4]才可以存放一个int值
就算int 是0在计算中也是占用个32位表示:00000000 00000000 00000000 00000000 存入byte中即4个下标中均为0
int直接存入byte数组中及原理:

int a =1246;
二进制表示
|------高16位----------|  |---------低16位-------|
00000000 00000000 00000100 11011110
|   A         | |   B        | |   C         | |   D         |
[0]              [1]             [2]              [3]   放入byte[]数组原理,将这个2进制以8位为1个字节存入byte数组中从数组下标0开始存入
最后byte[]数组存储为这样
[0]=00000000   补码后00000000转10进制真实数值0
[1]=00000000   补码后00000000转10进制真实数值0
[2]=00000100   补码后00000100转10进制真实数值4
[3]=11011110   补码后10100010转10进制真实数值-34,
                         最后8位11011110最高位是符合位,1负0正,补码规则: 符号位不变, 其余各位取反,
                         最后+1得到:10100010 0100010=34+负号"1"所以=-34
转换过程中进行&运算就是高位舍去,通俗就是不需要的数据清0处理,下面琢行说明:

由于byte只有8位,int32位,所以我们需要位移,把前面的每8位一组移动到最后8位上面来进行计算,其他数值都不参与计算
int a =1246;
byte[] b = new byte[4];
第一步:
b[0] = (byte) (a >> 24 & 0xff);
将00000000 00000000 00000100 11011110 A区域移动到D区域往右边推动24位,主要获取A取的值
00000000 00000000 00000100 11011110
                                                   00000000 00000000 00000100 11011110形成这样的
空白的数据被抹掉就是0表示,移动后超出了D区域数据属于溢出情况也舍掉最后形成如下
00000000 00000000 00000000 00000000
最后做&计算,这里移动了24位,右边的数据都被溢出了,做不做这个计算都没影响,还是表示下
00000000 00000000 00000000 00000000
00000000 00000000 00000000 11111111  &计算0xFF的2进制
-------------------------------------------------------
 00000000 00000000 00000000 00000000 结果还是0

第二步:
b[1] = (byte) ((a >> 16) & 0xff);
将00000000 00000000 00000100 11011110 B区域移动到D区域往右边推动16位,主要获取B取的值
00000000 00000000 00000100 11011110
                                  00000000 00000000 00000100 11011110形成这样的
空白的数据被抹掉就是0表示,移动后超出了D区域数据属于溢出情况也舍掉最后形成如下
00000000 00000000 00000000 00000000
00000000 00000000 00000000 11111111  &计算0xFF的2进制
---------------------------------------------------------
00000000 00000000 00000000 00000000 结果还是0

第三步:
b[2] = (byte) ((a >> 8) & 0xff);
将00000000 00000000 00000100 11011110 C区域移动到D区域往右边推动8位,主要获取C取的值
00000000 00000000 00000100 11011110
                 00000000 00000000 00000100 11011110形成这样的
空白的数据被抹掉就是0表示,移动后超出了D区域数据属于溢出情况也舍掉最后形成如下
00000000 00000000 00000000 00000100
00000000 00000000 00000000 11111111  &计算0xFF的2进制
-------------------------------------------------------
00000000 00000000 00000000 00000100补码后的2进制,上面的每一步最后都要参与补码,只是因为0就没写了
 转10进制最终结果是4

第四步:
b[3] = (byte) (a & 0xff);
将00000000 00000000 00000100 11011110 计算D区的值,由于D取直接就是在末尾8位上,所以不需要移动,
直接&计算,这里充分体现出来&0xFF计算就是清除其余不需要的数据,由于8位前还有0100 这么个数,
但是我们只需要后8位,所以&FF计算清除掉
00000000 00000000 00000100 11011110
00000000 00000000 00000000 11111111  &计算0xFF的2进制
-------------------------------------------------------
00000000 00000000 00000000 11011110结果
这个结果转10进制:222,可见是有问题的,int->byte我们只需要拿出最后8位出来进行处理11011110,
上面提过最高位(左边0的位置)是符号位:0表示正数,1表示负数
计算过程中只看后面7位1011110转10进制:94加上前面的符号得到-94,但这个数也不对
因为java采用补码存储整数
所以我们需要对1011110这个负数进行补码:负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
1011110
1100001再+1 1100001+1=1100010
最后1100010转10进制(只看后面7位100010):34前面加符号-34才是最终结果

二部分byte转int
对于一个单一的byte转int就是其本身,因为byte范围是-128--127如果输入超过这个数直接编译不通过
byte i=12;
int c=(int)i;
c=12;

像前面一部分,int转byte后得到的是一个4字节的byte[]数组,因为int长度就是4字节,不管值有多大或是0 byte[]也是4个长度,里面的值都是0;
继续上面的最终byte[]数组中的结果是
byte[] b ={0,0,4,-34};从下标0-4存的是int类型的高位到低位的顺序
|------高16位-----------| |---------低16位--------|
00000000 00000000 00000100 11011110
|   0         | |   0         | |   4         | |  -34        |
int 到byte是向右移动,那转换回来就是反其道而行之

第一步:
00000000 00000000 00000100 11011110原2进制
                                                   00000000 00000000 00000100 11011110原来下标0的数被移右动24位
所以获取下标[0]<<24左移24位
下标[0]=0转2进制
00000000 00000000 00000000 00000000  左移24位后的2进制,因为0怎么移动都是0
00000000 00000000 00000000 11111111  再进行&FF运算,为何要&FF后面比较直观,这里是0所以不讲解了
00000000 00000000 00000000 00000000  补码
-----------------------------------------
结果0

第二步:
00000000 00000000 00000100 11011110原2进制
                                  00000000 00000000 00000100 11011110原来下标1的数被移右动16位
所以获取下标[1]<<16左移16位,当然后面的2组数以不存在,移动后整个32位的2进制就是如下
下标[1]=0转2进制00000000
00000000 00000000 00000000 00000000  左移16位后的2进制,因为0怎么移动都是0
00000000 00000000 00000000 11111111  再进行&FF运算,为何要&FF后面比较直观,这里是0所以不讲解了
00000000 00000000 00000000 00000000  补码
-----------------------------------------
结果0

第三部分:
00000000 00000000 00000100 11011110原2进制
                 00000000 00000000 00000100 11011110原来下标2的数被移右动8位
所以获取下标[2]<<8左移8位,当然后面的1组数以不存在,移动后整个32位的2进制就是如下
下标[2]=4转2进制00000100
 00000000 00000000 00000100 00000000  左移8位后的2进制
&00000000 00000000 00000000 11111111  再进行&FF运算,为何要&FF后面比较直观,这里是0所以不讲解了
-----------------------------------------
 00000000 00000000 00000100 00000000
 00000000 00000000 00000100 00000000补码,正数补码是其本身
 结果100 00000000转10进制=1024

第四部分:
下标[3]=-34转2进制11111111 11111111 11111111 11011110
11111111 11111111 11111111 11011110原来下标3的数就是末尾8位没有发生过移动,所以不需要位移
00000000 00000000 00000000 11111111这里比较直观&FF计算去掉不需要的数据,可以称作清0操作
-----------------------------------------
00000000 00000000 00000000 11011110结果
00000000 00000000 00000000 11011110补码后
这时11011110并不是负数,因为现在是byte转int上面进行&FF运算后最高位是0,所以是正数,正数补码就是本身
-----------------------------------------
所以转10进制后=222
将最终的4个结果相加0+0+1024+222=1246

---------------------

本文来自 曦语 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_31232515/article/details/75009161?utm_source=copy

byte -> int的更多相关文章

  1. java中byte, int的转换

    最近在做些与编解码相关的事情,又遇到了byte和int的转换,看着那些关于反码.补码的说明依旧头疼,还是记下些实用的方法吧.int -> byte可以直接使用强制类型转换: byte b = ( ...

  2. 【转】java中byte, int的转换, byte String转换

    原文网址:http://freewind886.blog.163.com/blog/static/661924642011810236100/ 最近在做些与编解码相关的事情,又遇到了byte和int的 ...

  3. byte + byte = int

    byte+byte=int,低级向高级是隐式类型转换,高级向低级必须强制类型转换,byte<char<short<int<long<float<double

  4. (转)教你完全理解IO流里的 read(),read(byte[]),read(byte[],int off,int len)以及write

    背景:对于IO部分,总是感觉很虚,不能很好的理解其中的要义,其实仔细分析,掌握其中的规律,一切都会看起来十分的自然. 1 理解 1.1 从头总结 长期以来,java中的InputStream Outp ...

  5. 【Go入门教程4】变量(var),常量(const),内置基础类型(Boolean、数值 byte,int,rune、字符串、错误类型),分组,iota枚举,array(数值),slice(切片),map(字典),make/new操作,零值

    这小节我们将要介绍如何定义变量.常量.Go 内置类型以及 Go 程序设计中的一些技巧. 定义变量 Go 语言里面定义变量有多种方式. 使用 var 关键字是 Go 最基本的定义变量方式,与 C 语言不 ...

  6. python3 byte,int,str转换

    1 # bytes 与 int 2 b=b'\x01\x02' 3 num=int.from_bytes(b,'little') 4 print('bytes转int:',num) 5 6 b1=nu ...

  7. C++: byte 和 int 的相互转化

    原文链接:http://blog.csdn.net/puttytree/article/details/7825709 NumberUtil.h // // NumberUtil.h // MinaC ...

  8. java音视频编解码问题:16/24/32位位音频byte[]转换为小端序short[],int[],以byte[]转short[]为例

    前言:Java默认采用大端序存储方式,实际编码的音频数据是小端序,如果处理单8bit的音频当然不需要做转换,但是如果是16bit或者以上的就需要处理成小端序字节顺序. 注:大.小端序指的是字节的存储顺 ...

  9. java中的int与byte的转化

    java中的int与byte的转化 1.基础准备 1.1.原码 就是二进制码,最高位为符号位,0表示正数,1表示负数,剩余部分表示真值 1.2.反码 在原码的基础上,正数反码就是他本身,负数除符号位之 ...

随机推荐

  1. 2018-2019-2 20175311 实验二 《Java开发环境的熟悉》实验报告

    2018-2019-2 20175303 实验二 <Java开发环境的熟悉>实验报告 一.实验准备 1.了解掌握实验所要用到的三种代码 伪代码 产品代码 测试代码 2.IDEA中配置单元测 ...

  2. [UE4]Spline

    Spline和Spline Mesh的区别: 1.Spline Mesh是有实体表现的,Spline Mesh可以拉伸弯曲实体模型,Spline Mesh是具象. 2.Spline 只有曲线,没有实体 ...

  3. Promise的一点感悟~

    在什么大环境下? 今天要讨论的Promise,是js的同步|异步任务的概念下出来的 什么是同步?什么是异步? 我的理解: 一件事情Q 分三部分:Q1 ,  Q2  ,  Q3 同步方式完成: Q1 - ...

  4. JavaScript数组方法--slice、sort、splice

    数组常用方法应该只剩下最后这哥仨了,他们都是最早的ECMA-262标准的方法,结果写着写着,居然把他们写到最后了. slice:slice() 方法返回一个新的数组对象,这一对象是一个由 begin和 ...

  5. intellij idea 汉化

    intellij idea是IDEA的全称,现在最新版本的是intellij idea 16.这是一款公认的比较好的用于编程的软件.但是每次软件的发布都是全英文的,这让英文不好的人很是头疼.现在我告诉 ...

  6. Xeon Phi 《协处理器高性能编程指南》随书代码整理 part 4

    ▶ 第五章,几个优化 ● 代码 #include <stdio.h> #include <stdlib.h> #include <math.h> #define S ...

  7. kvm 虚机环境碰到的两个小坑

    1)当部署一个商用VA的时候,出现virsh version|grep "Using library" 返回错误,经过查看,发现里面有汉字,猜应该是这个原因导致无法检索到libvi ...

  8. Hibernate的查询方式

    Hibernate的查询的方式 OID检索 get或load方法进行的查询 对象导航检索 linkman.getCustomer(); HQL检索 用于接收hql语句进行查询,面向对象查询方式. 通过 ...

  9. docker swarm 部署服务时,限制服务启动后所在的机器

    借助容器技术,可以方便的在不同环境下部署服务,保证服务环境的一致性.docker swarm这个东西,可以方便的对容器进行编排管理. docker swarm集群中,有manager节点与worker ...

  10. sqlserver2008R2 全日志恢复 实例操作

    --创建数据库create database test;--将数据库日志备份模式设置为全日志ALTER DATABASE test SET RECOVERY FULL ; --查询.确认数据库日志备份 ...