当前位置: 首页 > news >正文

【C++sizeof与strlen】C++sizeof与strlen底层原理精讲:计算规则、指针数组特例、字符串内存坑点、笔试真题全方位复盘

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++内存底层根基。

http://www.zskr.cn/news/1461999.html

相关文章:

  • 【毕业设计】基于Python的大学生就业分析推荐系统基于Python+数据可视化的大学生就业信息推荐系统的设计与实现(源码+文档+远程调试,全bao定制等)
  • Node.js × 大模型:AIGC 工程化基础与异步流控总结
  • 模幂运算(Modular Exponentiation)
  • 基于ATmega328与TLC5510的DIY便携示波器设计与实现
  • Gemini 3.0前端实战指南:AI生成网页的真实能力与工作流重构
  • 学术写作新纪元!2026全流程AI写作辅助网站推荐指南
  • 如何用ESP32构建智能农业监测系统:从土壤传感器到云端可视化
  • 企业级短视频矩阵系统的底层架构演进:从工程自动化到AI流式管线
  • 3分钟快速上手:用untrunc无损修复损坏MP4视频的终极指南
  • 2026尤克里里选购攻略|4款高性价比尤克里里闭眼入推荐
  • Vibe Coding 实战复盘:从 0 到 1 做一个基金股票 AI 分析面板
  • Windows Defender彻底移除指南:如何简单快速释放系统性能
  • STM32F10x平台可用的完整3D打印固件:支持G代码运行、三轴同步运动和SD卡独立打印
  • 给无人机玩家的地物识别指南:看懂多光谱影像里的植被健康、水体污染和土壤湿度
  • 2026年北京亦庄高端置业楼盘参考:北京豪宅推荐、北京十大豪宅、北京顶级豪宅、北京二中学区房、北京大平层、北京经开区改善住宅优选盘点 - 海棠依旧大
  • 从源头制造到选型落地:2026防爆流量计实力厂家与选择建议 - 品牌推荐大师1
  • 从‘连连看’到人脸验证:图解Siamese Network核心思想,用PyTorch+MNIST带你轻松入门
  • 终极Windows窗口调整指南:如何用WindowResizer打破尺寸限制?
  • 别再让程序跑飞了!用STM32CubeMX的LL库搞定IWDG和WWDG,附赠超时时间计算器
  • # Openneuro数据集下载指南(已成功)
  • OpenCV-Python实战:手把手教你写一个颜色滑块调试器(附HSV/RGB完整代码)
  • 实战应用:不依赖claude code桌面版,在快马平台用ai生成可部署的个人博客系统
  • 电吹管新手选购攻略:3款高性价比型号实测推荐
  • 梯度下降不收敛?从缺失值与离群点的数学本质看特征缩放机制
  • 【AI产品战略级预判力】:掌握这6步路线图反向解码法,提前11个月锁定下一代爆款工具入场窗口
  • 从内存视角拆解float与double:手把手带你用C/Java验证IEEE 754编码
  • 基于白光干涉仪的超薄薄膜微观形貌表征及晶圆检测应用研究
  • 避坑指南:Docker部署MySQL 8.0时,如何正确初始化lower_case_table_names参数(附数据迁移方案)
  • 2026 年知识 IP 线下会销操盘公司选哪家:专业优选测评 - 思溯深度专栏
  • 氨氮/COD/水质检测仪哪个牌子靠谱?国产品牌采购选型,绥净环保参数解析 - 品牌推荐大师