Learning C++ 之 2.3 变量的size大小以及sizeof操作符

时间:2021-12-02 17:50:41

想你之前在2.1节学习的那样,变量的基础定义,初始化和声明,内存在现代机器中都是以byte的形式存在,每个单元都有一个明确的地址。从这一点上来讲,可以把内存想象成一个个小的空间,而变量名是找到这些空间的一个名字。

然而这个类比并不完全准确,因为变量往往并不是只占用一个byte的位置。因此一个变量往往会使用2,4或者8个连续的地址来存储数据。使用内存的size的大小取决于变量的数据类型。幸运的是,通常我们通过变量名来访问内存地址,而不是直接访问地址空间,所以没有必要关注这些是怎么实现的。

有几个理由需要我们必须知道变量所支持的空间大小:

首先一个变量占有的内存数越多,那么它包含的信息就越多。因为每一个bit包含数字0或者1,所以每个内存空间有两种可能。

2 bit就有四种可能:

bit 0 bit 1
0 0
0 1
1 0
1 1

3 bit有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位的空间,就有2的n次方中可能性。一个8bit的数据就有2的8次方中可能,也就是256.

变量的大小限制了他所能存储数据的多少,使用更多字节的变量可以保存更大变量的值。我们在之后具体讨论变量类型的时候再来具体确认这个问题。

其次来说,电脑都是由有限的空闲内存的。每当我们定义一个变量的时候,这个变量就会占据一小部分内存空间,知道变量使用结束。因为现在的电脑通常会有很多内存,所以只是简单的定义几个变量,对内存没有什么影响。但是如果要是定义上万个变量,那么每个变量占一个bit还是8个bit,对总体的内存就影响很大了。

C++基础数据类型的size:

先一个显然的问题就是C++的每一个基础变量类型个战了多少内存空间呢?你可能感到奇怪的是这些变量占用的内存取决于编译器的不同以及计算机架构的不同。

C++标准组织只是确认了每种数据类型占用的最小类型:

Category Type Minimum Size Note
boolean bool 1 byte  
character char 1 byte May be signed or unsigned
Always exactly 1 byte
  wchar_t 1 byte  
  char16_t 2 bytes C++11 type
  char32_t 4 bytes C++11 type
integer short 2 bytes  
  int 2 bytes  
  long 4 bytes  
  long long 8 bytes C99/C++11 type
floating point float 4 bytes  
  double 8 bytes  
  long double 8 bytes

然而真正的变量的size的大小取决于你的编译器。为了解决这个问题,C++提供了一个简答的元算符来计算变量或者类型的size,sizeof()。这是一个一元操作符,可以返回数据或者变量的size大小,你可以像下面的例子一样使用:

#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, may not be supported by your compiler
    std::cout << "char32_t:\t" << sizeof(char32_t) << " bytes" << std::endl; // C++11, may not be supported by your compiler
    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, may not be supported by your compiler
    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;
}

下面是在我的机器上的输出结果:

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

这个结果可能跟你的运行环境有关,因此你的机器上的结果可能会不一样。当然你不能计算void类型的大小,因为他没有size,所以编译器会报错。

当然你也可以直接用一个变量名来计算:

    int x;
    std::cout << "x is " << sizeof(x) << " bytes" << std::endl;

x is 4 bytes

我们将会在后续的课程中具体探讨每个变量的size大小,最后也会有一个附中表。