首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >深入剖析 C 语言中 strlen 和 sizeof 的核心区别

深入剖析 C 语言中 strlen 和 sizeof 的核心区别

作者头像
fashion
发布2025-12-31 17:43:39
发布2025-12-31 17:43:39
140
举报

在 C 语言学习过程中,strlen 和 sizeof 是两个高频出现的 “计算工具”,但很多初学者容易将它们混淆,甚至在实际开发中因误用导致程序 bug。本文将从概念定义、计算逻辑、使用场景三个维度,结合具体代码示例,帮你彻底理清二者的核心区别。

一、先明确:二者根本不是 “同一类东西”

要区分 strlen 和 sizeof,首先要记住一个关键前提 ——它们的本质属性完全不同

  • sizeof:是 C 语言的关键字(不是函数),作用是计算 “变量或数据类型在内存中占用的字节数”,计算结果在编译阶段就已确定(属于 “编译期常量”)。
  • strlen:是 C 标准库 <string.h> 中提供的函数,作用是计算 “字符串中有效字符的个数”(不包含字符串结束标志 '\0'),计算结果在程序运行阶段才确定。

这个本质差异,决定了它们后续所有的使用区别。

二、核心区别对比:5 个维度带你看透

为了更直观地理解,我们通过 “计算对象、是否包含 '\0'、结果时机、返回值类型、适用范围”5 个维度进行对比,并结合代码示例验证。

1. 计算对象:“内存大小” vs “字符串长度”
  • sizeof:计算的是变量 / 数据类型的内存占用量,无论对象是否为字符串,只要是合法的 C 数据类型(如 int、char、数组、结构体等),都能计算。
  • strlen:仅能计算以 '\0' 结尾的字符串(如字符数组、字符串常量),如果传入非字符串(如普通 int 数组),会因找不到 '\0' 导致内存越界,结果不可控。
代码示例 1:计算字符数组

#include <stdio.h>

#include <string.h>

int main() {

// 定义一个字符数组,存储 "hello"(末尾会自动添加 '\0')

char str[] = "hello";

// sizeof:计算数组在内存中的总字节数(h e l l o \0 → 6个字节)

printf("sizeof(str) = %zu\n", sizeof(str)); // 输出:6

// strlen:计算字符串有效字符数(不包含 '\0' → 5个字符)

printf("strlen(str) = %zu\n", strlen(str)); // 输出:5

return 0;

}

代码示例 2:计算非字符串(int 数组)

#include <stdio.h>

#include <string.h>

int main() {

int arr[] = {1, 2, 3, 4};

// sizeof:计算int数组的总字节数(每个int占4字节,4个元素 → 16字节)

printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出:16(32位/64位系统均为4字节/int)

// strlen:错误用法!int数组无 '\0',会越界访问,结果随机

printf("strlen(arr) = %zu\n", strlen((char*)arr)); // 结果不可控,可能是任意值

return 0;

}

2. 字符串场景:是否包含结束符 '\0'

这是二者在字符串计算中最直观的区别:

  • sizeof:会包含字符串末尾的 '\0'(因为 '\0' 是字符串在内存中的一部分,占用 1 个字节)。
  • strlen:仅计算 '\0' 之前的有效字符,不包含 '\0'
代码示例 3:显式添加 '\0' 的对比

#include <stdio.h>

#include <string.h>

int main() {

// 手动定义字符数组,包含 '\0'

char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'};

printf("sizeof(str) = %zu\n", sizeof(str)); // 输出:6(包含 '\0')

printf("strlen(str) = %zu\n", strlen(str)); // 输出:5(不包含 '\0')

// 如果去掉 '\0':

char str2[5] = {'h', 'e', 'l', 'l', 'o'};

printf("sizeof(str2) = %zu\n", sizeof(str2)); // 输出:5(数组长度固定为5)

printf("strlen(str2) = %zu\n", strlen(str2)); // 结果随机(找不到 '\0',越界)

return 0;

}

3. 结果时机:编译期确定 vs 运行期确定
  • sizeof:在程序编译时就会根据变量 / 类型的定义计算出结果,运行时直接使用编译好的常量值,效率更高。
  • strlen:在程序运行时才会从字符串起始地址开始遍历,直到遇到 '\0' 才停止计数,结果依赖运行时的内存数据。
代码示例 4:编译期 vs 运行期的验证

#include <stdio.h>

#include <string.h>

// 编译期:sizeof 可用于定义数组长度(因为结果是编译期常量)

char str1[sizeof("hello")] = "hello"; // 合法:sizeof("hello")=6,数组长度为6

// 运行期:strlen 结果是运行期值,不能用于定义数组长度(编译报错)

// char str2[strlen("hello")] = "hello"; // 错误:variable length array declaration not allowed at file scope

int main() {

printf("sizeof(str1) = %zu\n", sizeof(str1)); // 输出:6

printf("strlen(str1) = %zu\n", strlen(str1)); // 输出:5

return 0;

}

4. 返回值类型:size_t 统一,但意义不同

二者的返回值类型都是 size_t(无符号整数类型,定义在 <stddef.h> 中),但数值的 “意义” 完全不同:

  • sizeof 的返回值:表示 “字节数”(如 int 类型返回 4,char 数组返回长度)。
  • strlen 的返回值:表示 “字符个数”(仅针对字符串,且不包含 '\0')。
5. 适用范围:“万能计算” vs “字符串专属”

工具

适用场景

不适用场景

sizeof

所有数据类型(int、char、数组、结构体、指针等)

无(只要语法合法,均可计算)

strlen

以 '\0' 结尾的字符串(字符数组、字符串常量)

非字符串类型(int 数组、结构体、指针等)

三、易混淆场景:指针与数组的区别

在指针和数组的场景中,sizeof 和 strlen 的表现很容易让人迷惑,这里单独拎出来分析。

场景 1:数组名 vs 指针变量
  • 数组名:在 sizeof 中表示 “整个数组”,计算数组总字节数;在 strlen 中表示 “数组首元素地址”,计算字符串长度。
  • 指针变量:无论指向什么类型,sizeof 都计算 “指针本身的字节数”(32 位系统 4 字节,64 位系统 8 字节);strlen 计算指针指向的字符串长度(需确保以 '\0' 结尾)。
代码示例 5:数组名与指针的对比

#include <stdio.h>

#include <string.h>

int main() {

char str[] = "hello"; // 数组

char *p = str; // 指针,指向数组首元素

// 1. sizeof 对比

printf("sizeof(str) = %zu\n", sizeof(str)); // 输出:6(数组总字节数)

printf("sizeof(p) = %zu\n", sizeof(p)); // 输出:8(64位系统,指针占8字节)

// 2. strlen 对比

printf("strlen(str) = %zu\n", strlen(str)); // 输出:5(数组首地址开始的字符串长度)

printf("strlen(p) = %zu\n", strlen(p)); // 输出:5(指针指向的字符串长度)

return 0;

}

场景 2:字符串常量作为参数

当字符串常量(如 "hello")直接作为参数时:

  • sizeof("hello"):计算字符串常量的总字节数(包含 '\0',结果为 6)。
  • strlen("hello"):计算字符串常量的有效字符数(不包含 '\0',结果为 5)。

printf("sizeof(\"hello\") = %zu\n", sizeof("hello")); // 输出:6

printf("strlen(\"hello\") = %zu\n", strlen("hello")); // 输出:5

四、总结:一张表分清二者区别

为了方便记忆,我们用一张表总结 strlen 和 sizeof 的核心区别:

对比维度

sizeof

strlen

本质

关键字(编译期计算)

库函数(运行期计算)

计算对象

变量 / 数据类型的内存占用字节数

以 '\0' 结尾的字符串的有效字符数

是否包含 '\0'

是(字符串场景)

结果时机

编译期确定

运行期确定

适用范围

所有数据类型

仅字符串(需 '\0' 结尾)数字不行

指针场景

计算指针本身的字节数(4/8 字节)

计算指针指向的字符串长度

五、避坑建议

  1. 计算字符串长度用 strlen:如果想知道字符串有多少个有效字符,直接用 strlen,不要用 sizeof - 1(虽然结果可能对,但逻辑不直观,且容易出错)。
  2. 计算内存占用用 sizeof:无论是数组、结构体还是基本类型,只要需要知道内存占用大小,就用 sizeof。
  3. 避免给非字符串用 strlen:如 int 数组、float 变量等,用 strlen 会导致内存越界,程序崩溃或结果随机。
  4. 注意指针的 sizeof:指针变量的 sizeof 只和系统位数有关(32 位 4 字节,64 位 8 字节),和指向的类型无关。//如int 4

掌握以上区别,你就能在 C 语言开发中轻松避开 strlen 和 sizeof 的 “坑”,写出更健壮的代码!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、先明确:二者根本不是 “同一类东西”
  • 二、核心区别对比:5 个维度带你看透
    • 1. 计算对象:“内存大小” vs “字符串长度”
      • 代码示例 1:计算字符数组
      • 代码示例 2:计算非字符串(int 数组)
    • 2. 字符串场景:是否包含结束符 '\0'
      • 代码示例 3:显式添加 '\0' 的对比
    • 3. 结果时机:编译期确定 vs 运行期确定
      • 代码示例 4:编译期 vs 运行期的验证
    • 4. 返回值类型:size_t 统一,但意义不同
    • 5. 适用范围:“万能计算” vs “字符串专属”
  • 三、易混淆场景:指针与数组的区别
    • 场景 1:数组名 vs 指针变量
      • 代码示例 5:数组名与指针的对比
    • 场景 2:字符串常量作为参数
  • 四、总结:一张表分清二者区别
  • 五、避坑建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档