一、变量
变量相对于常量(也就是字面量),是程序输入数据存储的容器。
前面提到过,计算机中存储数据的地方主要是寄存器和内存。我们在程序中定义的变量主要是使用内存存放数据,变量也就是容器,也就是若干内存单元。
在内存中的“容器”我们主要关注它的两个属性:
1.容器有多大空间
2.如何找到这个容器
首先是容器的空间,也就是有多少个二进制位。因为内存单元按字节编址、寻址,所以通常变量能存放数据的空间也是若干个字节即若干内存单元。变量的空间大小由定义变量时变量类型指定,类似于之前字面量的识别类型int、long long等在定义这个变量时就指定了变量的空间大小。
其次是如何找到容器,一是可以对这个容器起个唯一的名字,这样就能通过这个名字直接找到容器。但实际上变量也就是内存中一段连续的内存区域,我们要找到这块区域本质上还是要使用对内存空间的编址也就是变量的地址。C/C++中同时提供变量名和变量地址来找到内存中的变量。
当这两个属性确定之后,一个变量也就确定了。访问变量的方式有两种:
一是通过变量名直接访问,变量名会根据定义变量时的变量类型自动确定所访问的内存空间(位置和大小),这完全由变量本身决定。
二是通过变量的内存地址访问变量对应的内存空间,这种方式变量的地址只是这块内存空间的起始地址,要正确使用变量还需要指定要访问的内存空间大小,这涉及指针的概念,并不完全由这个变量本身决定。
值得注意的是,我们并没有关心这个“容器”中存放的内容是什么。有两个原因,一是既然是变量那么它其中所存放的内容是可以改变的,我们只关心程序在运行的某一时刻其中存放的数据。二是容器中存放的无差别的二进制串,这就说明容器中到底存放的内容有何意义也就是何值,完全是由使用它的程序员或者编译器去将这个二进制串解释成某种类型的值,例如一个变量的内存空间中存放的是一个字节11110001,我们既可以认为它表示的是十进制的241,也可以认为它存的是0000 1111取反加1得到的二进制串即-15,甚至可以解释为一个字符等。
还有一个比较特殊的问题,那就是变量作为一个“容器”是否为空?从逻辑上讲,如果没有对变量赋值那么可以认为这个变量是空的。但是既然时内存空间,必然会时刻存放着一个二进制串,因为内存中每一个位除了0/1并没由第三中状态。所以从这一点来看,一个变量总是不为空的。所以通常在定义变量后不会直接使用它的值,因为其中当前存放的二进制串不一定是我们想要的,它也不会提醒你“变量为空”,而是当作一个已经赋值过的变量。
二、整数型变量
变量的类型有两个作用,一是指定所占的内存空间大小,二是指定在直接使用变量名时将其中的二进制串如何解释。从指定所占空间大小方面来看,无论是整数类型变量还是其他任何类型的变量差别只是所占的空间大小不同。只是整数型变量在直接使用变量名时将其中存放的二进制串按整数规则解释为整数,其他类型也类似。
C/C++中整数型变量有多种:
类型 | 所占字节 |
---|---|
char | 1 |
short | 2 |
int | 4 |
long | 4 |
long long | 8 |
如果不加前缀修饰,默认是signed修饰,如果用unsigned修饰可以再产生5种新的类型:
类型 | 所占字节 |
---|---|
unsigned char | 1 |
unsigned short | 2 |
unsigned int | 4 |
unsigned long | 4 |
unsigned long long | 8 |
实际上基本类型决定了变量的空间大小即容器宽度,无论是signed还是unsigned修饰都不影响容器宽度。
signed和unsigned修饰只是按两种不同的方式将其中的二进制串解释成整数。
signed或者默认不加前缀:将二进