C++从零开始(三)何谓变量
本篇说明内容是C++中的关键,基本大部分人对于这些内容都是昏的,但这些内容又是编程的基础中的基础,必须详细说明。
数字表示
数学中,数只有数值大小的不同,绝不会有数值占用空间的区别,即数学中的数是逻辑上的一个概念,但电脑不是。考虑算盘,每个算盘上有很多列算子,每列都分成上下两排算子。上排算子有2个,每个代表5,下排算子有4个,每个代表1(这并不重要)。因此算盘上的每列共有6个算子,每列共可以表示0到14这15个数字(因为上排算子的可能状态有0到2个算子有效,而下排算子则可能有0到4个算子有效,故为3×5=15种组合方式)。
上面的重点就是算盘的每列并没有表示0到14这15个数字,而是每列有15种状态,因此被人利用来表示数字而已(这很重要)。由于算盘的每列有15个状态,因此用两列算子就可以有15×15=225个状态,因此可以表示0到224。易做图数字的每一位有0到9这10个图形符号,用两个易做图数字图形符号时就能有10×10=100个状态,因此可以表示0到99这100个数。
这里的算盘其实就是一个基于15进制的记数器(可以通过维持一列算子的状态来记录一位数字),它的一列算子就相当于一位易做图数字,每列有15种状态,故能表示从0到14这15个数字,超出14后就必须通过进位来要求另一列算子的加入以表示数字。电脑与此一样,其并不是数字计算机,而是电子计算机,电脑中通过一根线的电位高低来表示数字。一根线中的电位规定只有两种状态——高电位和低电位,因此电脑的数字表示形式是二进制的。
和上面的算盘一样,一根电线只有两个状态,当要表示超出1的数字时,就必须进位来要求另一根线的加入以表示数字。所谓的32位电脑就是提供了32根线(被称作数据总线)来表示数据,因此就有2的32次方那么多种状态。而16根线就能表示2的16次方那么多种状态。
所以,电脑并不是基于二进制数,而是基于状态的变化,只不过这个状态可以使用二进制数表示出来而已。即电脑并不认识二进制数,这是下面“类型”一节的基础。
内存
内存就是电脑中能记录数字的硬件,但其存储速度很快(与硬盘等低速存储设备比较),又不能较长时间保存数据,所以经常被用做草稿纸,记录一些临时信息。
前面已经说过,32位计算机的数字是通过32根线上的电位状态的组合来表示的,因此内存能记录数字,也就是能维持32根线上各自的电位状态(就好象算盘的算子拨动后就不会改变位置,除非再次拨动它)。不过依旧考虑上面的算盘,假如一个算盘上有15列算子,则一个算盘能表示15的15次方个状态,是很大的数字,但经常实际是不会用到变化那么大的数字的,因此让一个算盘只有两列算子,则只能表示225个状态,当数字超出时就使用另一个或多个算盘来一起表示。
上面不管是2列算子还是15列算子,都是算盘的粒度,粒度分得过大造成不必要的浪费(很多列算子都不使用),太小又很麻烦(需要多个算盘)。电脑与此一样。2的32次方可表示的数字很大,一般都不会用到,如果直接以32位存储在内存中势必造成相当大的资源浪费。于是如上,规定内存的粒度为8位二进制数,称为一个内存单元,而其大小称为一个字节(Byte)。就是说,内存存储数字,至少都会记录8根线上的电位状态,也就是2的8次方共256种状态。所以如果一个32位的二进制数要存储在内存中,就需要占据4个内存单元,也就是4个字节的内存空间。
我们在纸上写字,是通过肉眼判断出字在纸上的相对横坐标和纵坐标以查找到要看的字或要写字的位置。同样,由于内存就相当于草稿纸,因此也需要某种定位方式来定位,在电脑中,就是通过一个数字来定位的。这就和旅馆的房间号一样,内存单元就相当于房间(假定每个房间只能住一个人),而前面说的那个数字就相当于房间号。为了向某块内存中写入数据(就是使用某块内存来记录数据总线上的电位状态),就必须知道这块内存对应的数字,而这个数字就被称为地址。而通过给定的地址找到对应的内存单元就称为寻址。
因此地址就是一个数字,用以唯一标识某一特定内存单元。此数字一般是32位长的二进制数,也就可以表示4G个状态,也就是说一般的32位电脑都具有4G的内存空间寻址能力,即电脑最多装4G的内存,如果电脑有超过4G的内存,此时就需要增加地址的长度,如用40位长的二进制数来表示。
类型
在本系列最开头时已经说明了何谓编程,而刚才更进一步说明了电脑其实连数字都不认识,只是状态的记录,而所谓的加法也只是人为设计那个加法器以使得两个状态经过加法器的处理而生成的状态正好和数学上的加法的结果一样而已。这一切的一切都只说明一点:电脑所做的工作是什么,全视使用的人以为是什么。
因此为了利用电脑那很快的“计算”能力(实际是状态的变换能力),人为规定了如何解释那些状态。为了方便其间,对于前面提出的电位的状态,我们使用1位二进制数来表示,则上面提出的状态就可以使用一个二进制数来表示,而所谓的“如何解释那些状态”就变成了如何解释一个二进制数。
C++是高级语言,为了帮助解释那些二进制数,提供了类型这个概念。类型就是人为制订的如何解释内存中的二进制数的协议。C++提供了下面的一些标准类型定义。
·signed char 表示所指向的内存中的数字使用补码形式,表示的数字为-128到+127,长度为1个字节
·unsigned char 表示所指向的内存中的数字使用原码形式,表示的数字为0到255,长度为1个字节
·signed short 表示所指向的内存中的数字使用补码形式,表示的数字为–32768到+32767,长度为2个字节
·unsigned short 表示所指向的内存中的数字使用原码形式,表示的数字为0到65535,长度为2个字节
·signed long 表示所指向的内存中的数字使用补码形式,表示的数字为-2147483648到+2147483647,长度为4个字节
·unsigned long 表示所指向的内存中的数字使用原码形式,表示的数字为0到4294967295,长度为4个字节
·signed int 表示所指向的内存中的数字使用补码形式,表示的数字则视编译器。如果编译器编译时被指明编译为在16位操作系统上运行,则等同于signed short;如果是编译为32位的,则等同于signed long;如果是编译为在64位操作系统上运行,则为8个字节长,而范围则如上一样可以自行推算出来。
·unsigned int 表示所指向的内存中的数字使用原码形式,其余和signed int一样,表示的是无符号数。
·bool 表示所指向的内存中的数字为逻辑值,取值为false或true。长度为1个字节。
·float 表示所指向的内存按IEEE标准进行解释,为real*4,占用4字节内存空间,等同于上篇中提到的单精度浮点数。
·double 表示所指向的内存按IEEE标准进行解释,为real*8,可表示数的精度较float高,占用8字节内存空间,等同于上篇提到的双精度浮点数。
·long double 表示所指向的内存按IEEE标准进行解释,为real*10,可表示数的精度较double高,但在为32位Windows操作系统编写程序时,仍占用8字节内存空间,等效于double,只是如果CPU支持此类浮点类型则还是可以进行这个精度的计算。
标准类型不止上面的几个,后面还会陆续提到。
上面的长度为2个字节也就是将两个连续的内存单元中的数字取出并合并在一起以表示一个数字,这和前面说的一个算盘表示不了的数字,就进位以加入另一个算盘帮助表示是同样的道理。
上面的signed关键字是可以去掉的,即char等同于signed char,用以简化代码的编写。但也仅限于signed,如果是unsigned char,则在使用时依旧必须是unsigned char。
现在应该已经了解上篇中为什么数字还要分什么有符号无符号、长整型短整型之类的了,而上面的short、char等也都只是长度不同,这就由程序员自己根据可能出现的数字变化幅度来进行选用了。
类型只是对内存中的数字的解释,但上面的类型看起来相对简单了点,且语义并不是很强,即没有什么特殊意思。为此,C++提供了自定义类型,也就是后继文章中将要说明的结构、类等。
补充:软件开发 , C++ ,