【C++sizeof与strlen】C++sizeof与strlen底层原理精讲:计算规则、指针数组特例、字符串内存坑点、笔试真题全方位复盘
2026/6/4 19:11:14 网站建设 项目流程

0. 前言

在C++笔试选择题、程序填空题、公司面试手撕题中,sizeof 和 strlen是出场率最高、正确率最低的基础考点,没有之一。绝大多数开发者看似每天都在用这两个函数,实则完全不懂底层执行机制,遇到数组、指针、字符串、结构体、嵌套类型、const修饰类型的混合场景,几乎全员踩坑。

很多人固化两个错误认知:第一,认为sizeof是函数、strlen是关键字;第二,认为两者都可以计算字符串长度;第三,认为数组名永远代表整个数组大小。这三大误区,也是90%笔试错题的核心来源。

二者本质天差地别:sizeof是编译期运算符,计算内存占用大小;strlen是运行时库函数,计算有效字符长度。一个面向内存、一个面向内容;一个编译期求值、一个运行时遍历;一个适配所有数据类型、一个仅适配字符指针。

本篇文章将从底层原理出发,从零拆解 sizeof 与 strlen 的完整机制,全覆盖普通变量、数组、指针、字符串、结构体、类对象、嵌套类型、退化场景的计算规则,逐一破除全网高频易错坑点,搭配海量可编译实战代码、笔试真题案例,彻底吃透这两个基础但极易丢分的核心知识点,根治所有相关错题与工程隐性问题。

1. 核心本质区分(必背底层定义)

1.1 sizeof 详解

sizeof:C++内置编译期运算符,非函数、非库方法。

核心作用:计算数据类型/变量占用的内存字节数,在编译阶段直接计算出结果,运行时无任何计算开销。

核心特性:

1. 编译期求值,运行时不执行任何逻辑;

2. 支持所有数据类型:基础类型、数组、指针、结构体、类、容器;

3. 只关注内存大小,完全不关注内存中存储的内容;

4. 计算结果固定,不受变量赋值、内容修改影响。

1.2 strlen 详解

strlen:C语言标准库运行时函数,定义在 <cstring> 头文件中。

核心作用:遍历字符内存,统计'\0'结束符之前的有效字符个数

核心特性:

1. 运行时逐字节遍历内存计算,存在运行时开销;

2.仅支持 char* 字符指针/字符数组,不支持其他类型;

3. 依赖结束符 '\0',无结束符会内存越界、随机乱数、程序崩溃;

4. 只关注有效字符数量,和内存总大小无关。

1.3 一句话终极区分

sizeof 看内存占多大,strlen 看内容有多长;sizeof 编译期定死,strlen 运行时遍历。

2. sizeof 全覆盖计算规则与实战代码

2.1 基础数据类型 sizeof 计算

基础类型的内存大小由操作系统位数决定,这是笔试基础常识:

32位系统:int=4、long=4、指针=4;

64位系统:int=4、long=8、指针=8;

char 永远占1字节,double永远占8字节,不受系统位数影响。

#include <iostream> using namespace std; int main() { cout << "char:" << sizeof(char) << endl; cout << "short:" << sizeof(short) << endl; cout << "int:" << sizeof(int) << endl; cout << "long:" << sizeof(long) << endl; cout << "float:" << sizeof(float) << endl; cout << "double:" << sizeof(double) << endl; return 0; }

2.2 指针类型 sizeof 核心规则(高频考点)

万能铁律:所有指针类型,sizeof 结果只和系统位数有关,和指向的类型无关

无论 int*、char*、double*、void*、自定义类指针,指针本质就是地址:

32位系统所有指针占4字节;64位系统所有指针占8字节。

#include <iostream> using namespace std; int main() { int* p1 = nullptr; char* p2 = nullptr; double* p3 = nullptr; void* p4 = nullptr; // 所有指针大小一致 cout << "int* 大小:" << sizeof(p1) << endl; cout << "char* 大小:" << sizeof(p2) << endl; cout << "double* 大小:" << sizeof(p3) << endl; cout << "void* 大小:" &lt;&lt; sizeof(p4) &lt;&lt; endl; return 0; }

这是笔试超级高频坑点:很多人误以为不同类型指针大小不同,实际完全一致。

2.3 数组 sizeof 计算(重难点、易错之王)

2.3.1 全局数组/局部数组原生计算

数组名单独参与 sizeof 运算时,代表整个数组类型,计算结果为:数组总字节大小 = 单个元素大小 × 元素个数。

#include <iostream> using namespace std; int main() { int arr[10] = {0}; char str[20] = "hello"; // int数组:4 * 10 = 40字节 cout << "int数组总大小:" << sizeof(arr) << endl; // char数组:1 * 20 = 20字节 cout << "char数组总大小:" << sizeof(str) << endl; // 经典用法:自动计算数组元素个数 int cnt = sizeof(arr) / sizeof(arr[0]); cout << "数组元素个数:" << cnt << endl; return 0; }
2.3.2 数组退化致命坑点(90%人踩坑)

数组名不是永远代表数组!

数组名在以下场景会退化为首元素指针

1. 数组名赋值给指针变量;

2. 数组名作为函数参数传递;

3. 除了 sizeof、& 取地址外的绝大多数场景。

数组一旦退化,sizeof 结果变为指针大小,不再是数组总大小。

#include <iostream> using namespace std; // 数组传参,自动退化为指针 void test(int arr[]) { // 此处arr是指针,不是数组! cout << "函数内sizeof(arr):" << sizeof(arr) << endl; } int main() { int arr[10] = {0}; cout << "主函数sizeof(arr):" << sizeof(arr) << endl; test(arr); return 0; }

核心结论:函数参数数组本质是指针,无法通过sizeof计算数组真实长度,工程传数组必须额外传递长度参数。

2.3.3 数组取地址特殊规则

&数组名代表整个数组的地址,指针类型为数组指针,sizeof 依然获取数组总大小,不会退化。

3. strlen 全覆盖规则与致命坑点

3.1 strlen 标准计算逻辑

从传入的字符指针地址开始,逐字节向后遍历,遇到 '\0' 终止,返回终止符前的有效字符数量,不包含 '\0' 本身

3.2 字符串常量与字符数组 strlen 对比

#include <iostream> #include <cstring> using namespace std; int main() { // 字符串常量:自动补'\0' char* s1 = "hello"; // 字符数组:长度20 char s2[20] = "hello"; cout << "strlen(s1):" << strlen(s1) << endl; // 5 cout << "sizeof(s1):" << sizeof(s1) << endl; // 指针大小8 cout << "strlen(s2):" << strlen(s2) << endl; // 5 cout << "sizeof(s2):" << sizeof(s2) << endl; // 数组大小20 return 0; }

清晰区分:strlen 只看有效字符,sizeof 只看内存占用。

3.3 strlen 崩溃高危场景(工程必避)

3.3.1 无 '\0' 结束符内存越界

字符数组手动赋值、未补结束符时,内存无终止标记,strlen 会一直向后遍历,造成内存越界访问、程序崩溃、随机数值

#include <iostream> #include <cstring> using namespace std; int main() { // 手动赋值,无默认'\0' char str[5]; str[0] = '1'; str[1] = '2'; str[2] = '3'; str[3] = '4'; str[4] = '5'; // 无结束符,结果随机、大概率崩溃 cout << strlen(str) << endl; return 0; }
3.3.2 空指针、野指针传入 strlen

strlen 内部直接解引用指针,传入 nullptr、野指针会直接触发段错误,程序闪退。

4. 字符串高频笔试真题(满分解析)

下面覆盖全网最经典、正确率最低的四道真题,一次性吃透所有字符串 sizeof/strlen 考点。

真题1:字符串常量指针

char* s = "abcd"; sizeof(s); // 8(64位指针) strlen(s); // 4

真题2:固定长度字符数组赋值短字符串

char s[10] = "abcd"; sizeof(s); // 10 数组总内存 strlen(s); // 4 有效字符

真题3:字符数组完整填充无结束符

char s[4] = "abcd"; sizeof(s); // 4 strlen(s); // 未知,无'\0',内存越界

真题4:数组传参退化

void fun(char s[]) { cout << sizeof(s); // 8,退化为指针 }

5. 结构体与类 sizeof 计算(进阶考点)

sizeof 计算结构体/类大小时,遵循内存对齐规则,不是简单的成员大小累加,这是进阶笔试高频考点。

#include <iostream> using namespace std; struct Test { char a; // 1字节 int b; // 4字节 }; int main() { // 并非 1+4=5,内存对齐后为8字节 cout << sizeof(Test) << endl; return 0; }

核心补充:结构体存在内存填充、对齐规则,后续专项章节会深度精讲,本章只需记住 sizeof 会计算对齐后的总内存大小。

6. 终极易错点汇总(全覆盖避坑)

1. sizeof 是运算符、编译期求值;strlen 是库函数、运行时求值;

2. 所有指针 sizeof 大小一致,只看系统位数,和指向类型无关;

3. 数组传参、赋值会退化指针,sizeof 不再获取数组大小;

4. strlen 依赖 '\0',无结束符必然越界崩溃;

5. strlen 不统计结束符,sizeof 统计数组完整内存;

6. 字符串常量默认补 '\0',手动字符数组赋值不补;

7. 禁止对非 char* 类型使用 strlen,编译报错;

8. 结构体、类 sizeof 遵循内存对齐规则,并非简单累加。

7. 工程级编码规范

1. 计算数组元素个数,仅能在定义数组的局部作用域使用 sizeof(arr)/sizeof(arr[0]);

2. 函数传数组必须附带长度参数,禁止依赖 sizeof 计算;

3. 使用 strlen 前必须保证字符内存带有 '\0' 结束符;

4. 字符操作优先使用 string 类,规避 strlen 越界风险;

5. 严禁对野指针、空指针执行 strlen 操作。

8. 全文总结

本篇文章彻底拆解了 sizeof 与 strlen 的底层本质、计算规则、适用场景、所有高频易错坑点,全覆盖基础类型、指针、数组、字符串、结构体、函数传参等笔试、工程核心场景。

彻底打破开发者对这两个工具的浅层认知,从编译期原理、数组退化机制、内存遍历逻辑三个维度,根治99%的相关错题与线上内存越界BUG,夯实C++内存底层根基。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询