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

sizeof和strlen的区别

sizeof和strlen的区别

  • 一、本质不同:运算符 vs 库函数
  • 二、求值时机:编译期常量 vs 运行时计算
  • 三、测量核心:总内存大小 vs 有效字符长度
    • 32 位系统输出
  • 四、职责分离:`sizeof` 问结构,`strlen` 问内容
  • 五、常见陷阱:函数参数中的数组退化
  • 六、安全性差异
  • 七、全面对照总结表

一、本质不同:运算符 vs 库函数

  • sizeof是 C/C++ 语言内置的运算符(关键字),由编译器直接处理,无需包含任何头文件
  • strlen是 C 标准库提供的函数,声明在<string.h>中,使用时必须包含该头文件。
维度sizeofstrlen
本质运算符(关键字)函数
所需头文件<string.h>(C++ 中为<cstring>
作用对象类型名、变量名、表达式const char*(以'\0'结尾的字符串)

二、求值时机:编译期常量 vs 运行时计算

  • sizeof:在编译阶段计算结果,等价于一个常量,不依赖程序实际运行。
  • strlen:在程序运行时从传入地址逐个扫描内存,直到遇见'\0'才停止。
#include<stdio.h>#include<string.h>intmain(void){chars[]="abc";// 编译器分配 4 字节:'a','b','c','\0'printf("sizeof(s) = %zu\n",sizeof(s));// 编译时已知printf("strlen(s) = %zu\n",strlen(s));// 运行时遍历return0;}

输出

sizeof(s) = 4 strlen(s) = 3

讲解

  • 数组s被初始化为"abc",编译器分配 4 个字节(含结尾'\0')。sizeof(s)在编译时就被替换为常数4
  • strlen(s)在运行时s的首地址向后扫描,数到'\0'前一共 3 个字符,返回3

三、测量核心:总内存大小 vs 有效字符长度

  • sizeof:测量类型或对象占用的总内存字节数。若对象是字符数组,会包含结尾的'\0'
  • strlen:测量字符串中有效字符的个数绝不包含结尾的'\0'
#include<stdio.h>#include<string.h>intmain(void){charstr[]="hello";// 数组 —— 实际占据 6 字节char*p="hello";// 指针 —— p 只存一个地址printf("=== 对字符数组 str ===\n");printf("sizeof(str) = %zu\n",sizeof(str));// 整个数组大小printf("strlen(str) = %zu\n",strlen(str));// 有效字符数printf("\n=== 对指针 p ===\n");printf("sizeof(p) = %zu\n",sizeof(p));// 指针变量自身大小printf("strlen(p) = %zu\n",strlen(p));// 指针所指字符串长度return0;}

输出(64 位系统)

=== 对字符数组 str === sizeof(str) = 6 strlen(str) = 5 === 对指针 p === sizeof(p) = 8 strlen(p) = 5

32 位系统输出

=== 对字符数组 str === sizeof(str) = 6 strlen(str) = 5 === 对指针 p === sizeof(p) = 4 strlen(p) = 5

讲解

  • 数组strsizeof(str)返回6(5 个字母 + 1 个'\0'),32 位与 64 位系统结果完全相同。strlen(str)返回5(遇'\0'停止,不计入结束符)。
  • 指针psizeof(p)64 位系统下返回 8,在32 位系统下返回 4,只与系统位数有关,p指向什么内容完全无关strlen(p)始终返回5,因为它沿着指针地址计算有效字符长度,至'\0'停止,不受系统位数影响。

四、职责分离:sizeof问结构,strlen问内容

  • sizeof只关心“这个变量 / 类型本身占多大空间”。不读取内存,不关心里面存的是什么。
  • strlen只关心“从这个地址开始,存放着一个多长的字符串”。必须读取内存,以'\0'为唯一终止标记。
    因此:
  • 数组名sizeof→ 得到整个数组的字节数。
  • 指针变量sizeof→ 得到指针变量自身的大小(4 或 8 字节)。
  • strlen对数组名和指针一视同仁,都是从给定地址向后数非'\0'字符。

五、常见陷阱:函数参数中的数组退化

数组作为函数参数传递时,会退化为指针。此时在函数内部使用sizeof(形参名)将无法获得原数组大小,只能得到指针大小。而strlen可以继续正常工作。

#include<stdio.h>#include<string.h>voidexamine(chararr[]){// 形参等价于 char *arrprintf("在函数内部:\n");printf(" sizeof(arr) = %zu <-- 这是指针的大小,不是数组的大小\n",sizeof(arr));printf(" strlen(arr) = %zu <-- 这才是字符串的真正长度\n",strlen(arr));}intmain(void){charstr[]="hello";printf("在 main 中 sizeof(str) = %zu\n\n",sizeof(str));examine(str);return0;}

输出(64 位系统)

在 main 中 sizeof(str) = 6 在函数内部: sizeof(arr) = 8 <-- 这是指针的大小,不是数组的大小 strlen(arr) = 5 <-- 这才是字符串的真正长度

讲解

  • mainsizeof(str)正确反映数组总大小6
  • 传入函数后,形参arr虽写作数组形式,但本质是指针sizeof(arr)返回指针变量的大小8,丢失了原数组的长度。
  • strlen(arr)不受影响,依然从地址扫描,得到正确长度5

🔑编程铁律:函数内处理字符串时,要长度请用strlen,或显式传入长度参数,不可依赖sizeof


六、安全性差异

  • strlen有越界风险:必须扫描到'\0'才停止。若传入的指针不是指向以'\0'结尾的有效字符串,将导致未定义行为,可能读取非法内存甚至崩溃。
  • sizeof不访问内存:仅根据类型信息在编译期推算大小,没有越界风险,极其安全。
char*dangerous=(char*)0x100;// 任意地址// strlen(dangerous); // 未定义行为,极可能崩溃// sizeof(*dangerous); // 等价于 sizeof(char),安全得到 1

七、全面对照总结表

比较维度sizeofstrlen
是什么运算符(关键字)函数
头文件<string.h>/<cstring>
计算时机编译时(VLA 除外)运行时
计算对象类型、变量、表达式'\0'结尾的字符串(const char*
测量内容内存占用总字节数有效字符个数(不含'\0'
是否包含'\0'数组:包含;
指针:与内容无关
不包含
对数组返回整个数组大小返回内部字符串长度
对指针返回指针变量自身大小(4/8 字节)返回指针所指字符串长度
在函数参数中数组退化 → 返回指针大小仍可正确求字符串长度
安全性不访问内存,无越界依赖正确的'\0',否则可能越界
结果是否为编译期常量多数情况,运行时值

记忆口诀

  • sizeof:问 “变量 / 类型 占多大坑” ——编译时定,不读数据。
  • strlen:问 “坑里字符串有多长 (别把末尾\0当字符)” ——运行时数,认\0为止。
http://www.jsqmd.com/news/819469/

相关文章:

  • Figma设计稿自动化生成代码:基于Gemini AI的CLI工具实践指南
  • 2026学生小提琴实测推荐,1000-2000元按预算抄作业,新手琴童精准适配
  • AgentStack:基于DAG编排的多智能体协作框架实战指南
  • Festo电缸经销商哪家好?Festo气缸经销商哪家好?仓敷隔震代理商哪家好?2026仓敷隔震/Festo代理商推荐 - 栗子测评
  • Go泛型实战经验总结:何时应该在新老项目中采用泛型
  • 7大推荐系统/算法框架对比
  • 你的编码器数据准吗?聊聊增量编码器应用中的3个常见坑与FPGA避坑方案
  • 2010-2024年省级农村居⺠消费价格指数
  • 双向DC-AC逆变器在整流与逆变模式下的无缝切换控制
  • 2026年靠谱的佛山不锈钢毛细管厂家综合对比分析 - 品牌宣传支持者
  • AMiner:研究生必备 AI 科研工具|文献调研・文献管理・代码复现一站式平台(基于 GLM 大模型)
  • CompressO:终极免费视频压缩神器,一键释放95%存储空间的完整指南
  • Kali实战进阶:从监听模式到WPA2握手,一步步破解Wi-Fi密码
  • THK代理商哪家好?2026THK滚珠丝杆经销商推荐:进口丝杆代理商推荐+THK花键经销商推荐清单 - 栗子测评
  • Petastorm实战:构建端到端TensorFlow训练管道的7个步骤
  • Go语言进程守护工具Custodian:轻量级高可用进程管理实践
  • NotebookLM播客化军规级配置(仅限前500名开发者获取的prompt工程模板+声学环境补偿表)
  • 川西旅拍MV哪家靠谱?川西婚前影像哪家好?2026成都婚前旅拍微电影+川西旅拍婚前影像推荐盘点 - 栗子测评
  • 双端最新最全 绅士《杀戮尖塔2》MOD爬塔党必备热门MOD整合包 热门的多种角色 实用辅助功能 附保姆级使用教程!手机版通用
  • 基础知识:理解股市中的买预期,卖兑现 / (Buy the Rumor, Sell the News)完全解析
  • 人机协同智能体(Human-in-the-loop)设计模式与最佳实践
  • THK中国区代理有哪些?THK经销商哪家好?2026THK总代经销商推荐:THK无尘油脂供应商+THK轴承经销商推荐 - 栗子测评
  • SpringBoot + Vue 计算机毕设项目管理系统(源码可分享)
  • signaldb-cli:响应式数据库开发利器,一键构建现代化Web应用
  • 川西目的地婚礼拍摄哪家好?2026川西目的地婚礼拍摄工作室精选,定格专属浪漫时刻 - 栗子测评
  • BGA243测试插座的高频与极端温度解决方案
  • 别再死磕有监督了!用PyTorch复现Mean Teacher,让你的小样本数据集也能‘卷’起来
  • RocketMQ 入门到原理实战全讲明白了!第二章
  • 手把手教你用Verilog在Cyclone FPGA上实现肤色识别(OV5640摄像头驱动)
  • 2026高精度导轨供应商推荐:高精度导轨批发厂家+进口导轨代理商+THK直线导轨经销商推荐汇总 - 栗子测评