为什么你一定要懂16进制?
核心一句话:其实计算机需要的只是二进制,需要十六进制的是我们人
我们了解最基本的进制转换,但是想一下,是不是大多数都是基于数字之间的进制转换
,比如常见的十进制和二进制互转
,一般关于进制转换,有很多的在线工具,要去用:
我们人看,就是数字66
,但是计算机不行,它看不懂,你必须给它转换成它认识的,那就是二进制,也就是0和1组成的数据
,所以我们看是66,计算机看就是1000010
所谓的X进制,就是逢x进一位
,比如10进制,就是逢十进一,二进制就是逢二进一,那么16进制就是逢16进1了!
这是最基本的进制知识!
十六进制(简写为hex)在数学中是一种逢16进1的进位制。一般用数字0到9和字母A到F表示,其中:A-F相当于十进制的10-15,这些称作十六进制数字
(重点记忆)。
例如十进制数57,在二进制写作111001,在16进制写作39。
不同电脑系统、编程语言对于16进制数值有不同的表示方式:
C语言、C++、Shell、Python、Java语言5及其他相近的语言使用前缀“0x”,例如“0x5A3”。开头的“0”令解析器更易辨认数,而“x”则代表十六进制(就如“O”代表八进制)。在“0x”中的“x”可以大写或小写。对于字符量C语言中则以
x+两位十六进制数
的方式表示,如xFF。
所以,理解16进制的一个关键,要知道什么是十六进制数,也就是组成十六进制的数据,(A-F,0-9),其中A-F相当于十进制的10-15,比如一个大写的A
或者数字6
就是一个十六进制数!
关于表示方式,我们可以记住最常见的形式就是
其中最常用(或常见)表示十六进制数值的方式是将 '0x' 加在数字前
再次强化十六进制数,这个其实就是指的十六进制是有哪些基本元素组成的,实际上就是由我们知道的十进制数字0-9和10-15,你想一个,十六进制,就是逢16进1,就好比十进制逢10进一,那十进制基本数字区间就是0-9有10个数,而16进制其实就是0-15,总共有16个数,只不过超过9以后的10,11,12,13,14,15
用大写字母A,B,C,D,E,F
表示!
所以你可以再次思考下,无论16进制还是二进制,其实都是在我们熟知的十进制表示,比如二进制,就是逢2进1,包含两个数字0和1,而16进制就是逢16进1,包含16个数,就是0-15,不过为了表示方便,加以区分,16进制会在前面添加0x
作为标识!
比如一个数字9
,这样大家都会认为是十进制数字9,如果是0x9
大家就知道这是16进制了,0x
指定它是16进制,9
是这个16进制的本体,那么16进制的0x9
转换成二进制其实就是对本体的9
做转换,而这个9就是十进制的9,转换成二进制就是1001
,所以十六进制数字9对应的二进制为1001。
16进制中的每个数字用4个bit存储,所以,一个byte就可以存储两个16进制数,比如16进制0x9
就是一个9,使用4bit存储,每个bit上存储的要么是0要么是1,所以16进制的数字9对应的二进制是1001,那么16进制的19
对应的二进制则是1 1001
,而16进制的119
对应的二进制则是1 0001 1001
!(要了解,这完全得益于一个十六进制数用4bit存储)
但是如果是十进制的话,就没那么快算出二进制了,比如十进制数字9的二进制是1001,那么十进制数字19的二进制呢?十进制数字119的二进制呢?是不是有点费劲,需要计算一番才行?
因此,你会发现,16进制和二进制之间转换是比十进制和二进制之间的转换容易的
那为什么16进制与二进制的转换就容易许多呢?
主要还是那个十六进制的每个数用4bit存储
,再说的细一点就是16是2的整数次幂,而10不是,因此,16进制转二进制就要比10进制转二进制容易!
接着需要了解的就是为啥16进制用的比较多,很重要,得记住?、
- 我们需要找一个与二进制转换比较友好的(必须是2的整数次幂),可以理解成16进制是刚刚好的那个值,再往上32进制可读性差,我们记起来费劲,往后八进制表达的内容不如16进制多
- 由于一个字节有8bit,而一个16进制数是一个字节的一般,两个16进制数刚好1字节
所以啊,16进制就是刚刚好的那一个!
到了这里,我们就学到了一个新的表述数据的方式,就是16进制,就是用0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
这16个数去表示的一种数据格式,当然,为了简洁表示,把10,11,12,13,14,15
用字母A,B,C,D,E,F
表示,所以所谓的16进制数据就是由0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
这16个元素去表示的,每一个元素被称为一个16进制数
,然后还要记住的就是一个16进制数用4个bit去表示,也就是一个16进制数占0.5个字节,2个16进制数据刚好占1个字节
数据存储都是需要转换为2进制加载进内存,所以你如果要存储一个16进制数,那么就要把16进制数转换为2进制才行,怎么转,就是根据一个16进制数占0.5个字节(4bit)去转换,比如16进制数0x19
,要注意0x
是个标识,代表是一个16进制的19,而不是十进制的19,然后根据每个16进制数用4个bit存储,这里有两个16进制数就是1和9
,也就是总计用8个bit去存储,画个图也就是这样:
每一格代表1bit的空间,这里有8bit,接下来就是把16进制数据0x19
存进去,分别把1和9
转换成2进制,9是1001
:
1还是1
:
就这样,16进制数据“0x19”占据了一个字节,8bit的空间!再举个例子,比如16进制数据0xA9
,它的存储如下:
你看这个16进制数A对应的就是十进制的10,而十进制的10对应的二进制就是1010,也就是说,所谓的16进制就是由
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F
这16个元素(16进制数)自由组合的数据,如果要存储16进制的话,就是把每一个16进制数作为10进制转换成2进制后存储在内存中,每一个16进制数占据0.5个字节,也就是4bit!
为什么用4bit存储呢?因为最大的16进制数就是F对应的十进制就是15,而15对应的二进制就是1111,刚好4bit够用!
OK,到了这里,你需要清晰明了的懂以下两个知识点了:
- 16进制是怎么表示的?
- 16进制如何存储的?
接着,我们要聊内存地址!切记,当我们聊内存的时候,你就把各个进制的数据该如何存储
这么一回事忘掉,比如16进制如何存储的就和我们要聊的内存地址毫无关系
!
OK,那我们开始内存地址的学习~
我们经常说内存啊,硬盘啊这些,其实都是存储设备,就是可以存储数据的,你平常写的程序代码这些,无论你是用记事本写的,还是用IDE工具写的,刚开始都是存储在硬盘上,也就是你电脑上的C盘,D盘这些,桌面就是在C盘,这些数据只要你写好保存好,不管你关机还是开机,数据一直都在不会丢失!
硬盘空间大,可以存储的东西多,但是它数据传输比较慢,因此,程序要想执行起来,必须把相应的数据加载进内存(比硬盘快很多)中才行,要从内存中把数据在交给CPU进行执行处理!
那这个时候,你就得想,无论你这个程序数据是刚开始存在硬盘上还是需要运行的时候加载进内存中,那么内存和硬盘都要有地址,为啥?因为他们得存储数据,就得把一定的空间分配给这些数据进行存储,那么每个空间就得有地址,只有地址,才能找到这些数据,就好比,你买快递得提供你的收货地址,没有收货地址,就找不到你,也给你送不了货啊!
因此,我们程序中的每一个数据,在内存上都会有一个对应的地址,就是为了后面用到可以找到它
另外还要清楚的就是,这个地址是计算机做的事情,它会把所有的数据加载进内存,然后给这些数据编好地址,哪个数据在哪,计算机都知道,所以内存地址这个东西就是给计算机看的,而我们看的则是引用(针对java来说)
重点来了:
计算机内存中最小的单位是bit,最基本的单位是字节,1字节(byte)= 8位(bit)
为什么最小的单位是bit呢?因为数据是要转换成0和1
组成的二进制数据进行存储,那么一个0或者一个1就刚好占据1bit,而1bit表示的太少,就以1字节也就是8bit为最基本单位:
这个时候就有个非常重要的知识了,我们前面说了,你把数据存储在内存中,需要有个地址,方便后续找到该数据,因此就有了内存地址
这么一说,相当于一间屋子的门牌号,比如上述表示的8bit空间存储的就是16进制数据0xA9
,这个时候我得给这个空间编个号,也就是给个地址,后续通过这个地址好找到这个数据~
怎么编号呢?注意了,我们使用16进制给内存地址编号
,不要走神了,更重要的是,我们把8bit也就是1字节作为一个内存地址
,也就是按字节编址
,什么意思呢?
比如我们要分苹果,8个苹果装1筐,那就是每筐有8个苹果,然后就会这样编号(按筐编号):
这个时候你就知道了,编号1的一筐里面8个苹果,编号加一也就是编号2就是下一筐了,里面也是8个苹果……这就是所谓的按筐编号
接着看我们的按字节寻址
,我们把1字节(一筐)作为一个内存地址,也就是8bit(一筐苹果),然后用16进制去编这个号:
这个时候,我们如果找到0x0001
这个内存地址,就找到了这块内存空间:
也就是1个字节,8bit的大小,取出里面的数据10101001
,这是二进制的,转换成16进制就是0xa9
或者0xA9
(大小写都行)!
OK,以上看完,你就要明白用16进制按字节编址是怎么回事了!