- 核心定义
- 语法和参数
- 工作原理和时机
- 返回值
- 代码示例
- 一张图看懂区别
- 总结与关键点
核心定义
sizeof: 一个操作符 (Operator),不是函数,它用于计算数据类型或变量在内存中所占用的字节数,它是在编译时就确定的值。strlen: 一个库函数,定义在<string.h>头文件中,它用于计算字符串的长度,即字符串中第一个\0(空字符) 之前出现的字符个数,它是在运行时计算的。
语法和参数
| 特性 | sizeof |
strlen |
|---|---|---|
| 类型 | 操作符 | 函数 |
| 头文件 | 无需任何头文件 | 需要包含 <string.h> |
| 语法 | sizeof(类型或变量) |
strlen(const char *str) |
| 参数 | 类型名 (如 int, char) 或变量 (如 a, arr) |
必须是一个以 \0 结尾的字符串指针 |
工作原理和时机
这是两者最根本的区别。

(图片来源网络,侵删)
sizeof 的工作原理
sizeof 在编译阶段由编译器处理,它查看变量的类型或类型本身,然后根据目标平台的内存布局规则计算出其大小。
- 对于变量:
sizeof返回该变量类型所占的字节数。 - 对于数组名:
sizeof返回整个数组在内存中占用的总字节数,而不是指针的大小,这是sizeof和strlen最常见的“陷阱”所在。
strlen 的工作原理
strlen 在程序运行时执行,它接收一个字符指针,然后从这个指针指向的内存地址开始,一个字节一个字节地向后遍历,直到它遇到第一个值为 \0 的空字符为止,它返回已经遍历过的字符个数。
注意:strlen 没有找到 \0,它会一直向后读,直到访问到非法内存,导致程序崩溃(段错误)。
返回值
| 特性 | sizeof |
strlen |
|---|---|---|
| 返回值类型 | size_t (一个无符号整型) |
size_t (一个无符号整型) |
| 返回值含义 | 内存占用的字节数 | 字符串的字符个数 |
| 单位 | 字节 | 字符 |
重要提醒:因为 strlen 返回的是 size_t(无符号类型),所以下面这种代码是错误的,会产生意想不到的结果:

(图片来源网络,侵删)
if (strlen("hello") - 5 < 0) { // 错误!
// ...
}
// "hello"的长度是5, 5-5=0, 0<0为false。
// 但如果换成 strlen("hi") - 5, 2-5=-3,由于是无符号数,-3会变成一个很大的正数,条件永远为true。
代码示例
示例 1:基本用法
#include <stdio.h>
#include <string.h> // 必须包含 strlen 的头文件
int main() {
char c = 'A';
char str[] = "Hello"; // 字符串 "Hello\0"
// --- sizeof ---
printf("sizeof(char) = %zu\n", sizeof(char)); // 输出: sizeof(char) = 1
printf("sizeof(c) = %zu\n", sizeof(c)); // 输出: sizeof(c) = 1
printf("sizeof(str) = %zu\n", sizeof(str)); // 输出: sizeof(str) = 6 (H,e,l,l,o,\0)
printf("sizeof(\"Hello\") = %zu\n", sizeof("Hello")); // 输出: sizeof("Hello") = 6
// --- strlen ---
printf("strlen(str) = %zu\n", strlen(str)); // 输出: strlen(str) = 5 (不计算\0)
printf("strlen(\"Hello\") = %zu\n", strlen("Hello")); // 输出: strlen("Hello") = 5
return 0;
}
示例 2:sizeof vs strlen 在数组上的关键区别
这是面试和实际开发中最容易出错的地方。
#include <stdio.h>
#include <string.h>
int main() {
char arr[] = "Hello"; // 在栈上分配了一个6字节的数组 ['H','e','l','l','o','\0']
char *ptr = "Hello"; // ptr 是一个指针,指向只读区中的字符串常量 "Hello"
// --- sizeof ---
printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出: 6 (整个数组的大小)
printf("sizeof(ptr) = %zu\n", sizeof(ptr)); // 输出: 4 或 8 (取决于系统,是指针变量本身的大小)
// --- strlen ---
printf("strlen(arr) = %zu\n", strlen(arr)); // 输出: 5 (从arr指向的位置开始找\0)
printf("strlen(ptr) = %zu\n", strlen(ptr)); // 输出: 5 (从ptr指向的位置开始找\0)
return 0;
}
示例 3:strlen 的危险性(未找到 \0)
#include <stdio.h>
#include <string.h>
int main() {
char arr[5] = {'H', 'e', 'l', 'l', 'o'}; // 注意:这个数组没有以 '\0'
// sizeof 依然安全,因为它只关心分配了多少空间
printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出: 5
// strlen 会发生危险!它会从 'H' 开始读,一直读下去,直到在内存中偶然找到 '\0'
// 这会导致未定义行为,通常是程序崩溃(段错误)
// printf("strlen(arr) = %zu\n", strlen(arr)); // <--- 危险!不要运行这行!
return 0;
}
一张图看懂区别
假设我们有 char str[] = "Hi";,它在内存中是这样分布的:
内存地址 (示例) +----+----+----+
| 'H'| 'i'| '\0'|
+----+----+----+
^ ^
| |
str[0] str[2] (str[2] == '\0')
|
str (数组名,代表首元素地址)
-
sizeof(str):- 问编译器:“这个叫
str的数组占多少空间?” - 编译器回答:“
'H'占1字节,'i'占1字节,'\0'占1字节,总共 3字节。” - 结果:3
- 问编译器:“这个叫
-
strlen(str):
(图片来源网络,侵删)- 问程序:“从
str指向的地址开始,有几个字符,直到遇到'\0'?” - 程序运行时,从地址
'H'开始数:'H'(1),'i'(2),下一个是'\0',停止。 - 结果:2
- 问程序:“从
总结与关键点
| 特性 | sizeof |
strlen |
|---|---|---|
| 本质 | 编译时操作符 | 运行时函数 |
| 作用 | 计算内存字节数 | 计算字符串字符数 |
| 参数 | 类型/变量 | 必须是以 \0 结尾的字符串 |
| 安全性 | 总是安全的 | 不安全,若字符串未以 \0 结尾会越界访问 |
| 对数组名 | 返回整个数组的大小 | 返回字符串的长度 |
| 对指针 | 返回指针本身的大小 | 返回指针指向的字符串的长度 |
如何记忆?
sizeof-> Size of Memory -> 内存大小 -> 计算字节数。strlen-> String Length -> 字符串长度 -> 计算字符数。
黄金法则:
当你想知道一个变量或类型占多少内存时,用 sizeof。
当你想知道一个以 \0 结尾的字符串有多长时,用 strlen。
