C语言高频面试题——sizeof和strlen的区别
1. 功能与用途
特性 | sizeof | strlen |
---|---|---|
功能 | 计算变量或类型所占的内存大小(字节) | 计算字符串的长度(字符数,不包含 \0 ) |
适用对象 | 任何数据类型或变量 | 以 \0 结尾的字符数组(字符串) |
返回值类型 | size_t (无符号整型) | size_t (无符号整型) |
2. 核心区别
sizeof
- 编译时计算:
- 对于静态数组或固定类型,
sizeof
的结果在编译时确定。 - 例如:
sizeof(int)
的结果由编译器直接确定。
- 对于静态数组或固定类型,
- 包含终止符
\0
:- 对于字符数组,
sizeof
会包含字符串末尾的\0
。 - 示例:
char str[] = "hello"; printf("%zu", sizeof(str)); // 输出 6(5个字符 + 1个'\0')
- 对于字符数组,
- 可作用于类型或变量:
- 可以直接对类型使用
sizeof
,例如sizeof(int)
。 - 也可以对变量使用,例如
sizeof(arr)
。
- 可以直接对类型使用
strlen
- 运行时计算:
- 必须遍历字符串直到遇到
\0
,因此结果在运行时确定。
- 必须遍历字符串直到遇到
- 不包含终止符
\0
:- 仅统计
\0
之前的有效字符数。 - 示例:
char str[] = "hello"; printf("%zu", strlen(str)); // 输出 5
- 仅统计
- 仅作用于字符串:
- 参数必须是一个指向以
\0
结尾的字符数组的指针。
- 参数必须是一个指向以
3. 示例对比
示例 1:字符数组
char arr[] = "hello";
printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出 6(包含 '\0')
printf("strlen(arr) = %zu\n", strlen(arr)); // 输出 5
示例 2:字符指针
char* ptr = "hello";
printf("sizeof(ptr) = %zu\n", sizeof(ptr)); // 输出 8(64位系统中指针占8字节)
printf("strlen(ptr) = %zu\n", strlen(ptr)); // 输出 5
示例 3:动态分配的内存
char* dynamic_str = malloc(10 * sizeof(char));
strcpy(dynamic_str, "hi");
printf("sizeof(dynamic_str) = %zu\n", sizeof(dynamic_str)); // 输出 8(指针大小)
printf("strlen(dynamic_str) = %zu\n", strlen(dynamic_str)); // 输出 2
free(dynamic_str);
4. 关键注意事项
sizeof
的常见陷阱
- 数组退化为指针:
- 当数组作为函数参数传递时,会退化为指针,此时
sizeof
返回指针大小而非数组大小。
void func(char arr[]) {printf("%zu", sizeof(arr)); // 输出 8(指针大小) }
- 当数组作为函数参数传递时,会退化为指针,此时
- 结构体对齐:
sizeof
计算结构体大小时会包含填充字节(内存对齐)。
struct Example {char c; // 1字节int i; // 4字节 }; printf("%zu", sizeof(struct Example)); // 输出 8(假设对齐到4字节)
strlen
的常见陷阱
- 未初始化的字符串:
- 如果字符串未以
\0
结尾,strlen
可能导致越界访问。
char str[5] = {'h', 'e', 'l', 'l', 'o'}; // 未显式添加 '\0' printf("%zu", strlen(str)); // 未定义行为(可能无限循环)
- 如果字符串未以
- 修改字符串内容:
- 如果字符串中间包含
\0
,strlen
会提前终止。
char str[] = "hello\0world"; printf("%zu", strlen(str)); // 输出 5(遇到第一个 '\0' 停止)
- 如果字符串中间包含
5. 使用场景
场景 | 使用 sizeof | 使用 strlen |
---|---|---|
计算数组容量 | sizeof(arr)/sizeof(arr[0]) | 不适用(无法获取数组容量) |
字符串长度 | 不适用(包含 \0 ) | 适用(统计有效字符数) |
动态内存分配 | 确定需要分配的字节数(如 malloc ) | 确定字符串所需的实际空间(需 +1 存储 \0 ) |
结构体内存布局 | 计算结构体总大小 | 不适用 |
总结
sizeof
:- 编译时确定内存大小。
- 适用于所有数据类型和变量。
- 包含字符串的终止符
\0
。
strlen
:- 运行时统计有效字符数。
- 仅适用于以
\0
结尾的字符串。 - 不包含终止符。
理解两者的区别可以避免以下典型错误:
- 用
sizeof
直接获取字符串长度(会导致多算一个\0
)。 - 用
strlen
计算数组容量(无法获取数组真实大小)。
示例错误代码:
char str[10] = "hello";
int len = strlen(str); // 正确:len = 5
int size = sizeof(str); // 正确:size = 10
int wrong_len = sizeof(str) - 1; // 错误:依赖 sizeof 计算字符串长度