不同的数据在计算机内存中占用的存储空间大小是不一样的。如果我们想要准确知道某个类型、变量或表达式在内存中占用了多少个字节(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() 方法。
