C++ sizeof 运算符

不同的数据在计算机内存中占用的存储空间大小是不一样的。如果我们想要准确知道某个类型、变量或表达式在内存中占用了多少个字节(Byte),就可以使用 sizeof 运算符。

C++ sizeof 基本用法

在 C++ 中,sizeof 是一个关键字,同时也是一个内置运算符。通过它可以直接查询某种类型占多少个字节,或者某个变量占多少个字节。

语法:

sizeof(数据类型)
sizeof(变量或表达式)

说明:

在使用 sizeof 时,小伙伴们需要清楚以下 3 个基本特点:

  • sizeof 是运算符,不是函数:虽然 sizeof(...) 带有小括号,看起来像函数调用,但它实际上是内置运算符。查询变量时虽然可以省略括号写成 sizeof age,但为了与 sizeof(int) 保持统一,平时建议都加上小括号写成 sizeof(age)。
  • 返回值的单位是字节(Byte):sizeof 返回的结果单位是字节,而不是二进制位(bit)。在计算机中,1 个字节包含 8 个二进制位。比如 sizeof(int) 返回 4,就表示占用 4 个字节,合 32 个二进制位。
  • 返回值的类型是 std::size_t:sizeof 计算出的结果本身也有类型,叫做 std::size_t。这是 C++ 标准库专门用来表示内存大小、元素个数等非负整数的无符号整型。

在目前主流的 64 位系统中,常见基础数据类型占用的字节数如下表所示。

基本类型常见字节数
数据类型 说明 常见字节数
char 字符型 1 个字节
bool 布尔型 1 个字节
short 短整型 2 个字节
int 整型 4 个字节
long 长整型 4 或 8 个字节
long long 超长整型 8 个字节
float 单精度浮点型 4 个字节
double 双精度浮点型 8 个字节

示例 1:查询类型与变量的字节数

#include <iostream>

int main() {
    char grade = 'A';
    bool passed = true;
    int age = 20;
    double height = 1.75;

    std::cout << sizeof(char) << ' ' << sizeof(grade) << '\n';
    std::cout << sizeof(bool) << ' ' << sizeof(passed) << '\n';
    std::cout << sizeof(int) << ' ' << sizeof(age) << '\n';
    std::cout << sizeof(double) << ' ' << sizeof(height) << '\n';
    return 0;
}

运行结果如下。

1 1
1 1
4 4
8 8

分析:

从运行结果可以看出,在当前环境中,char 和 bool 各占 1 个字节,int 占 4 个字节,double 占 8 个字节。同时,直接查询类型名 sizeof(int) 与查询该类型的变量 sizeof(age),得到的字节数是完全一样的。

提示 C++ 标准规定 sizeof(char) 的结果固定为 1,而其他基础类型(尤其是 long)占多少字节可能会受编译器和系统平台影响。上表数字平时了解一下即可,拿不准时写一行 sizeof 测一下就知道了。

使用 sizeof 的注意事项

在日常使用 sizeof 运算符时,有 3 个重要规律需要大家搞清楚,下面我们结合具体示例逐一来看。

1. 变量大小由类型决定

对于基础类型的变量来说,它在内存中占多少个字节,从定义数据类型那一刻起就已经定下来了,跟变量里面当前装的数字是 1 还是 1000000 没有任何关系。

这就像在超市寄存柜租了一个标准尺寸的储物格:不管你在格子里只放了一把钥匙,还是塞满了一整个书包,这个储物格本身占据的空间大小都是固定不变的,如下图所示。

储物格存放不同物品但空间大小固定不变

示例 2:存入不同大小的数值

#include <iostream>

int main() {
    int small = 1;
    int large = 1000000;

    std::cout << sizeof(small) << '\n';
    std::cout << sizeof(large) << '\n';
    return 0;
}

运行结果如下。

4
4

分析:

small 保存的是 1,large 保存的是 1000000。虽然两个数值相差一百万倍,但由于它们都是 int 类型,在内存中都固定占用 4 个字节。

同样地,直接查询整数字面量 sizeof(1) 和 sizeof(1000000) 都是按默认的 int 类型计算,结果都是 4。而 sizeof(1.0) 因为小数字面量默认是 double 类型,所以结果是 8。

2. 查询表达式的结果大小

既然 sizeof 只看数据的类型,我们还可以把一条算术表达式放进 sizeof(...) 的括号里,用来验证表达式经过隐式类型转换之后变成了什么类型。

示例 3:查询表达式的结果大小

#include <iostream>

int main() {
    short a = 10;
    int b = 20;
    double c = 1.5;

    std::cout << sizeof(a) << '\n';
    std::cout << sizeof(a + b) << '\n';
    std::cout << sizeof(b + c) << '\n';
    return 0;
}

运行结果如下。

2
4
8

分析:

在这个例子中,变量 a 本身是 short 短整型,单独占 2 个字节。当 a 与 int 类型的 b 相加时,a 会先自动提升为 int 类型,相加的结果也是 int 类型,因此 sizeof(a + b) 返回 4。

而在第三行中,当 int 类型的 b 与 double 类型的 c 相加时,b 会先自动转换为 double 类型,相加的结果也是 double 类型,因此 sizeof(b + c) 返回 8。

3. 括号内的运算不会执行

这是 sizeof 非常特殊的一个性质:sizeof 是在程序编译阶段,直接根据括号内表达式的 “结果类型” 推算字节数的,不会在程序运行时真正去执行括号里的计算。

也就是说,如果在 sizeof(...) 的括号里写了自增(++)、自减(--)或者赋值操作,这些修改操作都不会生效。下面我们来看一个例子。

示例 4:括号内的自增不会执行

#include <iostream>

int main() {
    int num = 10;
    std::cout << sizeof(++num) << '\n';
    std::cout << num << '\n';
    return 0;
}

运行结果如下。

4
10

分析:

sizeof(++num) 输出了字节数 4,为什么下一行打印出的 num 依然是 10,没有变成 11 呢?

原因就在于编译器看到 ++num 时,只推算出它的结果类型是 int(占 4 个字节),在编译阶段就直接把 sizeof(++num) 替换成了数字 4,里面的 ++num 在程序运行时根本没有执行。因此小伙伴们平时写代码时要注意,千万不要把自增、自减或赋值操作写进 sizeof(...) 的括号里。

常见问题

1. 后面可以使用 sizeof 来求数组或字符串的长度吗?

要分情况来看,不能一概而论:

普通数组可以换算元素个数:在统计普通数组长度时,我们可以用整个数组占用的总字节数除以单个元素的字节数,算出数组里一共有多少个元素。

不能用来求 std::string 的字符个数:对 std::string 使用 sizeof 测出的只是字符串对象自身固定占用的管理结构大小,跟里面存了几个字无关。求字符串长度需要使用专门的 .length() 或 .size() 方法。

上一篇:

下一篇:

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号