变量
当我们创建一个变量时,它会被存储在内存中的两个地方之一:栈或堆。
C++ 中的原始数据
C++ 中的原始数据基本上构成了我们在程序中存储的任何类型的数据的基础。在 C++ 中,不同变量之间的唯一区别就是大小—这个变量占用内存大小的多少,这实际上是这些原始数据类型之间的唯一区别。
声明一个新变量的语句如下:
变量类型 变量名 [= 变量值]
变量类型 变量名 [= 变量值]
如
int variable;
或
int variable = 8;
int代表整数,它允许我们在给定的范围内存储一个整形数字。
按照传统,整形数据的大小为4字节(byte),实际上,数据类型的实际大小取决于编译器。这是一个带符号的整数,所以其可以存储的数字范围是±21亿。
可是为什么是21亿呢,实际上21亿并不准确,大概是21亿上下。我们来看看这20亿是怎么来的。
一个字节是8比特(bit),也就是说,4个字节就是32bits。因为这个数据类型是带符号的,也就是说它有正负,包含了一个符号,也就是负号,而负号会占用1bit,所以我们留给实际数字只有31位。每个bit可存储两个值,也就是0和1,所以一共有2^31,也就是约21亿(实际精确结果为 2,147,483,648,但是要留一位给0,所以应是2,147,483,647,粗略记为21亿就可以了)。
那么有没有办法只存储整数而不存储复数,也就是让32bits都用于存储数字呢?答案是当然有!我们可以这样定义一个整型变量:
unsigned int variable;
这里的 unsigned 意思是无符号数,也就是我们将用来存储符号的那 1 bit 也用于存储数字了。那么 2^32 是多少呢?当然是两倍,也就是约 42 亿了。
那么我们还有哪些数据类型呢?下面列出其它的数据类型:
数据类型 | 内存大小 |
---|---|
char | 1 byte |
short | 2 byte |
int | 4 byte |
long | 4 byte |
long long | 8 byte |
…… | …… |
当然还有很多的数据类型及其变化形式,但最基本的是这5个。
char 通常是用来存储字符的,我们可以给它赋值 65 ,也可以给它赋值 'A'(注意这里用的是单引号)。那我们可以给一个 int 类型的变量赋值字符吗?当然也可以。与字符 A 所绑定的数字就是 65。
既然数字是字符,字符是数字,那么他们之间又有什么联系呢?
我们先以 char 为例,看看下面两行代码输出的分别是什么:
char a = 65;
char b = 'A';
std::cout << a <<std:: endl;
std::cout << b <<std:: endl;
事实上,第一行输出的是 A,第二行输出的也是 A。因为我们在使用 char 作为 a 和 b 的数据类型,就是在告诉 cout 我们传入的是一个字符而不是数字。
如果我们将 char 换成 short 又会出现什么情况呢?
short a = 65;
short b = 'A';
std::cout << a <<std:: endl;
std::cout << b <<std:: endl;
运行一下可以看到,输出了两个 65。这是因为我们告诉了 cout 我们传入的是一个字数字而不是字符。
从上面的例子中可以看出,c++ 的数据类型并不局限于官方给出的建议用法,实际的使用方法还是取决于程序员。因此在这里想强调的是:数据类型之间唯一的真正区别是,当我们使用改数据类型创建一个变量的时候,将会分配多少内存。
如果我们想定义小数呢?那么我们可以采用 float 和 double 这两种数据类型:
float a = 5.5;
double b = 5.5;
但是你以为这样就结束了吗?还没有!尽管这里我们使用了 float 数据类型,但当我们在VS中将鼠标悬停在 a 变量上,我们可以发现它仍然被定义为了double类型。那么我们如何定义一个真正的 float 类型的变量呢?我们只需在所赋值后加一个 f(大小写均可)就可以了。
float a = 5.5f;
float 和 double 前也可以加 long 之类而组成变化形式,这里不多加讨论,只给出这两个数据类型所占的内存大小:
数据类型 | 内存大小 |
---|---|
float | 4 byte |
double | 8 byte |
bool 型是一个较为常见的类型,它的值只有两个:true或者flase。
但是如果我们尝试这样定义: bool a = true; 那么我们将会得到一个 1 的结果。因为计算机中没有对或错的说法,只有 0 和 1。所以基本上 0 就代表 false(bool a = false; 的输出是0),而 0 以外的任何东西都被认为是 true。bool 型只占用 1 byte 大小。什么?为什么是 1 byte 而不是 1 bit?事实上,它确实只占用 1 bit,但当我们需要从内存中获取或存储我们的 bool 时,我们没有办法寻址到每一个 bit,我们只能寻址到 bytes。正因如此,我们无法创建只有 1 bit 的内存空间。但是,我们可以将 8 个 bool 类型的值存放在1 byte 里面。
开头讲过,实际上数据类型所占空间大小取决于编译器,那么我们要怎样来检查编译器对某个数据类型的定义呢?我们可以用 sizeof() 进行检查:
//下面代码输出的是bool类型所占用的内存大小
std::cout << sizeof(bool) << std::endl;
//也可以不要括号,写成:
std::cout << sizeof bool << std::endl;
现在,有了这些原始类型,我们可以将其转换为指针(pointer)或者引用(reference)。指针可以通过在数据类型旁边写一个星号来声明,而引用则是在数据类型旁边加上一个&符号。
int* a = 1234; //这是指针
bool& b = true; //这是引用
指针和引用是一个非常大也及其复杂的问题,所以会在后面的章节单独进行学习。