• 详解 & 0xff 的作用


    占用字节数 & 取值范围

    Java一共有8种基本数据类型(原始数据类型):

    类型            存储要求               范围(包含)                默认值              包装类
    int           4字节(32位)          -2^31~ 2^31-1                  0               Integer
    short         2字节(16位)          -215~215-1                     0               Short
    long          8字节(64位)          -2^63~2^63-1                   0               Long
    byte          1字节(8位)           -2^7~2^7-1                     0               Byte
    float         4字节(32位)          -3.4e+38 ~ 3.4e+38            0.0f             Float
    double        8字节(64位)          -1.7e+308 ~ 1.7e+308           0               Double
    char          2字节(16位)          u0000~uFFFF(‘’~‘?’)         ‘0’              Character 
    boolean       1/8字节(1位)          true, false                  FALSE             Boolean

    对于float与double类型:

    内存结构:

    float类型: 内存中共占4个字节,32bit位,其中bit位从高到低,依次是1位符号位、8位指数位、23位尾数位;
    double类型:内存中共占8字节,64bit位,其中bit位从高到低,依次是1位符号位、11位指数位、52位尾数位;

    大端模式与小端模式

    大端模式是指数据的低位保存在内存的高地址中,而数据的高位保存在内存的低地址中.
    小端模式是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。

    大小端模式的由来

    在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器)。

    另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。因此就导致了大端存储模式和小端存储模式。

    大小端在内存中的存放方式举例

    例如:

    a) 16bit宽的数0x1234
    1.Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:

    1 内存地址
    2 0x4000
    3 0x4001
    4 存放内容
    5 0x34
    6 0x12

    2.Big-endian模式CPU内存中的存放方式则为:

    1 内存地址
    2 0x4000
    3 0x4001
    4 存放内容
    5 0x12
    6 0x34

    jvm使用的是大端

     原码、反码、补码知识

    源码

    源码就是数字对应的二进制表示。

    负数的源码 = 正数的源码取反再加1

    反码

    正数的反码就是源码自身。

    负数的反码就是:保持源码符号位不变,其余各个位取反。

    补码

    正数的补码就是源码自身。

    负数的补码就是: 反码基础上加1

    如何根据补码计算源码:

    1. 最高位如果是0,即为正数,其补码即为源码;
    2. 最高位如果是1,即为负数,对此补码再次计算补码,结果即为源码(即:补码的补码即为源码)。

    首先我们要都知道, &表示按位与,只有两个位同时为1,才能得到1, 0x代表16进制数,0xff表示的数二进制1111 1111 占一个字节.和其进行&操作的数,最低8位,不会发生变化.

    1. 只是为了取得低八位

    通常配合移位操作符>>使用

    例如:java socket通信中基于长度的成帧方法中,如果发送的信息长度小于65535字节,长度信息的字节定义为两个字节长度。这时候将两个字节长的长度信息,

    以Big-Endian的方式写到内存中

    1 out.write((message.length>>8)&0xff);//取高八位写入地址
    2 out.write(message.length&0xff);//取低八位写入高地址中


    例如,有个数字 0x1234,如果只想将低8位写入到内存中 0x1234&0xff
    0x1234 表示为二进制 0001001000110100

    0xff 表示为二进制 11111111

    两个数做与操作,显然将0xff补充到16位,就是高位补0

    此时0xff 为 0000000011111111

    与操作 1&0 =0 1&1 =1 这样 0x1234只能保留低八位的数 0000000000110100 也就是 0x34

    2. 保证补码的一致性

    我们只关心二进制的机器数而不关注十进制的值,那么byte &0xff只是对其最低8位的复制,通常配合逻辑或 ‘’|’'使用,达到字节的拼接,但不保证其十进制真值不变

    1 public static void main(String[] args) {
    2     byte b = -127;//10000001
    3     int a = b;
    4     System.out.println(a);
    5     a = b&0xff;
    6     System.out.println(a);
    7 }//输出结果-127,129

    乍一看,b是8位的二进制数,在与上0xff(也就是 11111111),不就是其本身吗,输出在控制台结果为什么是129呢?

    首先计算机内的存储都是按照补码存储的,-127补码表示为 1000 0001

    int a = b;将byte 类型提升为int时候,b的补码提升为 32位,补码的高位补1,也就是

    1111 1111 1111 1111 1111 1111 1000 0001

    负数的补码转为原码,符号位不变,其他位取反,在加1,正数的补码,反码都是本身

    结果是 1000 0000 0000 0000 0000 0000 0111 1111表示为十进制 也是 -127

    也就是 当 byte -> int 能保证十进制数不变,但是有些时候比如文件流转为byte数组时候,

    我们不是关心的是十进制数有没有变,而是补码有没有变,这时候需要&上0xff

    本例子中,将byte转为int 高24位必将补1,此时补码显然发生变化,在与上0xff,将高24重新置0,

    这样能保证补码的一致性,当然由于符号位发生变化,表示的十进制数就会变了

    1 1111 1111 1111 1111 1111 1111 1000 0001
    2 
    3 &
    4 
    5 0000 0000 0000 0000 0000 0000 1111 1111
    6 
    7 结果是
    8 
    9 0000 0000 0000 0000 0000 0000 1000 0001

    和原来的补码 一致,但是显然符号位变化了,表示的十进制数发生变化,变为129

    结论:

    java中基本类型从小扩展到大的数据类型时候,正数因为符号位是0,无论如何都是补零扩展,但是负数补零扩展和补符号位扩展完全不同,

    负数补符号位扩展,保证十进制数不变

    例如 byte>>>int -127自动按照补符号位扩展,在高24位补符号位1,表示的十进制数不变

    补零扩展,保证补码的一致性,但是表示的十进制发生变化

    例如,本例中byte提升为int,&0xff的操作

  • 相关阅读:
    hdu 1142 用优先队列实现Dijkstra
    POJ 2063 Investment 完全背包
    POJ 3260 多重背包+完全背包
    bignum 大数模板
    POJ 3468(树状数组的威力)
    POJ 3468 线段树裸题
    hdu 1058 Humble Numbers
    CodeForces 185A 快速幂
    POJ 1990 MooFest 树状数组
    设计模式(20)策略模式
  • 原文地址:https://www.cnblogs.com/msdn1433/p/13186203.html
Copyright © 2020-2023  润新知