CPP学习之——变量及数据如何存储在内存上(4.3)

一 概述

  • 计算机内存可以看做是一系列小文件柜,每个文件柜由许许多多排列成一列的小格子组成,每个格子都编了号,这些编号就是内存地址,变量一般放置在一个或多个格子里 ,每个格子都可存储一个值。
  • 变量名(例如variable)是贴在这些文件柜上的一个标签,用户可以通过变量名,无需知道变量的具体地址就可以方便地查找到变量,如图所示:

二 内存特性

  • 当你运行一个程序时,程序自动将一部分数据从磁盘文件加载到随机存储器(也叫RAM),所有变量都在RAM中生成,程序员在谈到内存时通常都是指RAM。
  • RAM不能讲数据和变量永久地保存在内存上,因此当程序运行结束或者断电后,这些数据和变量便从内存中释放或者丢失。

三 理解变量及内存需要明白的概念

  • 由于内存的这种特性,因此当我们定义一个变量时,我们必须告诉编译器该变量时什么类型:是整型,字符型,还是其他类型,编译器将根据我们定义的类型自动为变量预留出空间,然后做好放置这种类型的值的准备。
  • 每个格架是一个字节,如果我们定义的变量类型占2个字节,则它需要2个字节内存,也就是两个格子。
  • 假如我们想要深入地了解数据是如何存储的,我们就要理解"位"与"字节"的区别,以及二进制和十六进制的概念。

四 进制(二进制、八进制、十六进制)

4.1 引言

  • 我们都知道100这个数字的含义,但是计算机是否也像人一样明白100这个数字的意义内?
  • 答案是不,计算机实际上根本不知道什么是字母、数字、指令或程序,在它的内核,只是一些电路,在某个给定的结点,要么有很多电要么几乎没有电
  • 既然计算机不认识数字,那么它又是怎么表达数字的呢?

4.2 计算机的逻辑

  • 工程师根据计算机的这种特性,用1和0来代表每一段电路的真实状态(通电或者断电),计算机所知道的0或者1,其实就是通电时为1,断电时为0,而这种简单的逻辑又可延伸到任何方面,即判断眼下坐在电脑跟前的人"是你,还是不是你?",如果是你则为1,不是你则为0.

4.3 位和字节

  • 一旦决定用1和0代表真与假,那么二进制数字就很重要了,因为早期的计算机一次能够发送8位数字。
  • 很自然地用8位二进制数字开始编写代码——8位二进制数字也叫字节。
  • 如从00000000...11111111间的所有可能的组合,每一种组合便是8位计算机的一次传递量。
  • 假如是16位则一次传递从0000000000000000...1111111111111111之间的16位二进制数字,以此类推。

4.4 半字节和8位数的最大值

  • 8位二进制数字是一个字节,那么4个二进制数字就是半个字节,比如(1010 0101)中,1010是前半个字节,叫高8位,0101为后半个字节,叫低八位
  • 用8位二进制数可以表示256个不同的值,为什么?看一看位数,如果8位都为1(11111111),则值为255,如果8位都为0(00000000),则值为0,从0到255有256种可能的状态。有兴趣的观众可以用计算器算一下,假如还是不明白,我们接下来就讲解一下换算方法。

4.5 进制的换算

  • 10进制使用数字0-9,逢10进1
  • 因此我们可以这样来表示10的进位,10^0,10^1,10^2...
  • 我们知道任何数值的0次幂是1,所以如果要表示8,则为8*10^0,表示10则是10^1,100为10^2,111为1*10^2+1*10^1+1*10^0
  • 8进制使用数字0-8,逢8进1
  • 8的进位为8^0 8^1 8^2...,同理,八进制数111便是1*8^2+1*8^1+1*8^0=64+8+1=十进制数73

4.6 二进制转十进制

  • 那么前面的二进制数11111111便是1*2^1+1*2^2+1*2^3+1*2^4+1*2^5+1*2^6+1*2^7=1+2+4+8+16+32+64+128=255
  • 其他进制,比如16进制,转换十进制方法相同,在此就不多说了

4.7 十进制转八进制及其他进制

  • 要用8进制来表示十进制数字15,则是17,为什么是17呢,因为八进制17中的1代表8,7代表7个1,1个八加7个一等于15.依次类推,十进制15这个数可以用七进制表示为21,为什么是21呢,因为在七进制中没有数字8,为了表示十五需要2个七和1个一
  • 我们找出其中规律后,要将十进制转换为八进制,只需要将10进制数不断除以八就可以了,换一句话来说就是看这个10进制数中有多少个8的幂,比如说十进制数200,它里面最多包含两个8相乘,8*8假如再乘以8就是512,超过了200这个数,由此可知八进制的第四位为0,而用200除以64,等于3,那么第三位为3,检查余数为零,那么个位是零,200转换为8进制为3**^2+1*8^1+0*8^0,结果为310

4.8 十进制转二进制

  • 位数: 8 7 6 5 4 3 2 1
  • 幂次: 2^7 2^6 2^5 2^4 2^3 2^2 2^1 2^0
  • 值: 128 64 32 16 8 4 2 1
  • 要将65转换为二进制,可以遵循前面的方法,65比2^6=64大,又比2^7=128小,故第八位为0,65中只有一个64,故第七位为1,余数为1,比2^5(32)小,故第六位为0,1比2^4 2^3 2^2 2^1都小,故第五位、第四位、第三位、第二位都为0,由于余数还是为1,因为个位为1.
  • 转换过来为:01000001
  • 如果要验证一下,可将它再转换回去
  • 1*2^6+1*2^0=64+1=65

4.9 十六进制

  • 由于机器只懂0和1,而二进制数字又难以阅读,于是人们想出了一种更为简单的方式来表示相同的值,从二进制转换为十进制涉及到了数的操作,但是从二进制转换到十六进制就简单了,因为有一个很快捷的方法。

4.10 二进制转换十六进制演示

  • 比如说有一个二进制数11111100
  • 现在,我们将这个二进制数分成二组,就可以进行奇妙的转换
  • 1111 1100
  • 左边一组1111,在十进制中为15,在十六进制中为F
  • 右边一组1100,在十进制中为12,在十六进制中为C
  • 把这两个十六进制数放在一起就是FC,它的实际值为11111100,这种快捷方式永远成立。可以将任何长度的任何一个二进制数,缩减为每4位一组,将每组中的4位数转换成一个十六进制数,把这些十六进制数拼在一起就得到了在十六进制数中的结果。而将十六进制转换为十进制又非常简单。
  • 这就是汇编语言为什么使用十六进制的原因

五 参考

  • 二进制、八进制、十进制、十六进制之间的转换