在 C 语言学习过程中,strlen 和 sizeof 是两个高频出现的 “计算工具”,但很多初学者容易将它们混淆,甚至在实际开发中因误用导致程序 bug。本文将从概念定义、计算逻辑、使用场景三个维度,结合具体代码示例,帮你彻底理清二者的核心区别。
要区分 strlen 和 sizeof,首先要记住一个关键前提 ——它们的本质属性完全不同:
这个本质差异,决定了它们后续所有的使用区别。
为了更直观地理解,我们通过 “计算对象、是否包含 '\0'、结果时机、返回值类型、适用范围”5 个维度进行对比,并结合代码示例验证。
#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;
}
#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;
}
这是二者在字符串计算中最直观的区别:
#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;
}
#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;
}
二者的返回值类型都是 size_t(无符号整数类型,定义在 <stddef.h> 中),但数值的 “意义” 完全不同:
工具 | 适用场景 | 不适用场景 |
|---|---|---|
sizeof | 所有数据类型(int、char、数组、结构体、指针等) | 无(只要语法合法,均可计算) |
strlen | 以 '\0' 结尾的字符串(字符数组、字符串常量) | 非字符串类型(int 数组、结构体、指针等) |
在指针和数组的场景中,sizeof 和 strlen 的表现很容易让人迷惑,这里单独拎出来分析。
#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;
}
当字符串常量(如 "hello")直接作为参数时:
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 字节) | 计算指针指向的字符串长度 |
掌握以上区别,你就能在 C 语言开发中轻松避开 strlen 和 sizeof 的 “坑”,写出更健壮的代码!