从2.1节《详解变量的定义、初始化与赋值》的学习中我们了解到,现代计算机的内存通常是按byte大小的单元进行组织的,每个单元都是唯一的标识地址,从这个意义讲,我们可以形象地把内存看成一系列文件夹/邮箱,可以用来存放和检索信息,变量就是用来访问这些文件夹/邮箱的名称。
但是,这样的类比从某方面看也是不准确的——大多数的变量实际上占用超过一个字节的内存,单个变量可能使用2个、4个甚至8个连续的内存地址。变量占用的数据类型取决于其数据类型。幸运的是,由于我们通常使用变量名而不是内存地址访问内存,所以编译器能在很大程度上对我们隐藏处理不同大小变量的细节。
了解一个变量占用多少内存有几个好处。
首先,一个变量占用越多的内存,就应当能保存越多的信息。因为每个bit只能保存0或1,所以我们说一bit能够保存两个可能的值。
2bit可以存放4个可能的值:
bit 0 | bit 1 |
0 | 0 |
0 | 1 |
1 | 0 |
1 | 1 |
3bit可以存放8个可能的值:
bit 0 | bit 1 | bit 2 |
0 | 0 | 0 |
0 | 0 | 1 |
0 | 1 | 0 |
0 | 1 | 1 |
1 | 0 | 0 |
1 | 0 | 1 |
1 | 1 | 0 |
1 | 1 | 1 |
依次类推,一个n bit的变量可以存放2^n个可能的值,所以一个字节byte可以存放2^8(256)个可能的值。
变量的大小限制了其存储信息的能力,当我们接触更多不同类型的变量时会进一步了解这一点。
其次,计算机的可用内存是有限的,一旦我们声明了一个变量,只要这个变量还存在,就会占用一部分的空闲内存。由于现代计算机的内存通常很大,所以这通常不是问题(特别是只有几个变量的小程序),但是如果你的程序拥有巨量的变量(例如10,000个)或者可用内存相当有限(例如进行单片机开发时),使用1字节和8字节的变量性能开销就会是天壤之别。
C++基本数据类型的大小
接下来的问题就是如何确定变量占用内存的大小了,你可能会感到惊讶,一个给定数据类型实际上取决于编译器/计算机架构。
C++规定基本数据类型占用的最小内存如下:
种类 | 数据类型 | 最小占用内存 | 注 |
布尔型 | bool | 1 byte | |
字节型 | char | 1 byte | |
wchar_t | 1 byte | ||
char16_t | 2 bytes | C++11 | |
char32_t | 4 bytes | C++11 | |
整型 | short | 2 bytes | |
int | 2 bytes | ||
long | 4 bytes | ||
long long | 8 bytes | C99/C++11 | |
浮点型 | float | 4 bytes | |
double | 8 bytes | ||
long double | 8 bytes |
实际计算机上的变量大小可能与此不同,为了确定数据类型的大小,C++提供了一个操作符:sizeof。sizeof操作符为一元操作符,接受参数为变量名或者数据类型,以字节为单位返回其大小,你可以编译运行以下程序以了解你计算机上的变量大小。
#include <iostream>
int main()
{
std::cout << "bool:\t\t" << sizeof(bool) << " bytes" << std::endl;
std::cout << "char:\t\t" << sizeof(char) << " bytes" << std::endl;
std::cout << "wchar_t:\t" << sizeof(wchar_t) << " bytes" << std::endl;
std::cout << "char16_t:\t" << sizeof(char16_t) << " bytes" << std::endl; // 需编译器支持C++11
std::cout << "char32_t:\t" << sizeof(char32_t) << " bytes" << std::endl; // 需编译器支持C++11
std::cout << "short:\t\t" << sizeof(short) << " bytes" << std::endl;
std::cout << "int:\t\t" << sizeof(int) << " bytes" << std::endl;
std::cout << "long:\t\t" << sizeof(long) << " bytes" << std::endl;
std::cout << "long long:\t" << sizeof(long long) << " bytes" << std::endl; // 需编译器支持C++11
std::cout << "float:\t\t" << sizeof(float) << " bytes" << std::endl;
std::cout << "double:\t\t" << sizeof(double) << " bytes" << std::endl;
std::cout << "long double:\t" << sizeof(long double) << " bytes" << std::endl;
return 0;
}
使用Visual Studio 2013在64位机器上运行结果如下:
bool: 1 bytes char: 1 bytes wchar_t: 2 bytes char16_t: 2 bytes char32_t: 4 bytes short: 2 bytes int: 4 bytes long: 4 bytes long long: 8 bytes float: 4 bytes double: 8 bytes long double: 8 bytes
使用其他编译器/计算机得到的结果可能不同,注意不可以使用sizeof(void),因为void是无大小的,这么做会产生一个编译错误。
上述程序中的’\t’是一个特殊字符,用来插入制表符,在上述例子中,我们用它来对齐输出结果。以后谈论char数据类型的时候我们会讲到\t以及其他特殊字符。
我们也可以对一个变量名使用sizeof:
int x;
std::cout << "x is " << sizeof(x) << " bytes" << std::endl;
结果如下:
x is 4 bytes
You have noted very interesting details! ps decent website.
https://supersmash4flash.joomla.com/2-uncategorised/2-super-smash-flash-4-fighting-game
The paragon of unenastrdding these issues is right here!