1. 概述
在 C++ 编程中,sizeof和strlen是两个初学者容易混淆的运算符/函数。它们都与“大小”或“长度”相关,但本质、用途和计算方式截然不同。理解它们的区别对于正确处理内存、字符串和数据结构至关重要。
2. sizeof 运算符
sizeof是 C++ 中的一个编译时一元运算符,用于计算数据类型或对象在内存中所占的字节数。
2.1 基本特性
- 编译时计算:结果在编译时确定,不会在运行时计算。
- 单位是字节:返回的是
size_t类型的值。 - 作用于类型或表达式:可以对数据类型(如
int)或变量/表达式使用。
2.2 代码示例
#include <iostream> using namespace std; int main() { // 1. 对基本数据类型 cout << "sizeof(int): " << sizeof(int) << endl; // 通常为 4 cout << "sizeof(double): " << sizeof(double) << endl; // 通常为 8 cout << "sizeof(char): " << sizeof(char) << endl; // 总是 1 // 2. 对变量(无需括号,但建议使用) int arr[10]; cout << "sizeof(arr): " << sizeof(arr) << endl; // 10 * sizeof(int) // 3. 对指针 char *p = nullptr; cout << "sizeof(p): " << sizeof(p) << endl; // 指针大小(通常 4 或 8) cout << "sizeof(*p): " << sizeof(*p) << endl; // sizeof(char) = 1 // 4. 对结构体(考虑内存对齐) struct Student { int id; char name[20]; double score; }; cout << "sizeof(Student): " << sizeof(Student) << endl; return 0; }3. strlen 函数
strlen是 C 标准库(定义在<cstring>中)的一个运行时函数,用于计算C 风格字符串(以空字符 '\0' 结尾的字符数组)的长度。
3.1 基本特性
- 运行时计算:需要遍历字符串直到遇到 '\0'。
- 单位是字符个数:返回的是有效字符的数量,不包括结尾的 '\0'。
- 仅作用于字符串:参数必须是以 '\0' 结尾的字符数组(或指向它的指针)。
3.2 代码示例
#include <iostream> #include <cstring> using namespace std; int main() { // 1. 字符串字面量 const char *str1 = "Hello"; cout << "strlen(\"Hello\"): " << strlen("Hello") << endl; // 5 cout << "strlen(str1): " << strlen(str1) << endl; // 5 // 2. 字符数组 char str2[] = "World"; cout << "strlen(str2): " << strlen(str2) << endl; // 5 // 3. 手动构造的字符数组(必须包含 '\0') char str3[10] = {'H', 'i', '\0', '!'}; cout << "strlen(str3): " << strlen(str3) << endl; // 2(遇到第一个 '\0' 停止) // 4. 未以 '\0' 结尾的数组使用 strlen 是未定义行为! char dangerous[5] = {'a', 'b', 'c', 'd', 'e'}; // 没有 '\0' // cout << strlen(dangerous) << endl; // 危险!可能一直读取直到遇到内存中的 '\0' return 0; }4. 核心区别对比
| 对比项 | sizeof | strlen |
|---|---|---|
| 本质 | 编译时运算符 | 运行时库函数 |
| 作用对象 | 任何数据类型或表达式 | 仅限以 '\0' 结尾的字符串 |
| 计算内容 | 内存占用字节数 | 有效字符个数(不含 '\0') |
| 计算时机 | 编译时 | 运行时 |
| 参数 | 类型或表达式 | 字符串指针 |
| 对指针的处理 | 返回指针本身的大小 | 返回指针所指字符串的长度 |
| 包含 '\0' 吗? | 是(如果数组包含 '\0') | 否 |
| 头文件 | 语言内置,无需头文件 | #include <cstring> |
5. 典型混淆场景与代码分析
5.1 字符数组的 sizeof 与 strlen
#include <iostream> #include <cstring> using namespace std; int main() { char str[] = "C++"; // 等价于 char str[4] = {'C', '+', '+', '\0'}; cout << "sizeof(str): " << sizeof(str) << endl; // 输出 4(整个数组大小:4 个 char) cout << "strlen(str): " << strlen(str) << endl; // 输出 3(有效字符数,不含 '\0') // 对于指针(指向字符串) const char *p = "C++"; cout << "sizeof(p): " << sizeof(p) << endl; // 输出 8(64 位系统指针大小) cout << "strlen(p): " << strlen(p) << endl; // 输出 3(字符串长度) return 0; }5.2 动态分配内存时的大小计算
#include <iostream> #include <cstring> using namespace std; int main() { // 动态分配字符串 char *dynamic_str = new char[100]; strcpy(dynamic_str, "Dynamic"); cout << "sizeof(dynamic_str): " << sizeof(dynamic_str) << endl; // 指针大小(8) cout << "strlen(dynamic_str): " << strlen(dynamic_str) << endl; // 字符串长度(7) // 注意:sizeof 无法知道动态分配的内存块大小! // cout << sizeof(*dynamic_str) << endl; // 只是 sizeof(char) = 1 delete[] dynamic_str; return 0; }6. 常见错误与注意事项
- 用 sizeof 计算字符串长度:
sizeof("Hello")返回 6(包含 '\0'),而strlen("Hello")返回 5。 - 对指针使用 sizeof:
sizeof(指针)返回的是指针变量本身的大小,而不是它指向的数据大小。 - strlen 需要有效字符串:如果字符数组不以 '\0' 结尾,
strlen会导致未定义行为(可能访问越界)。 - sizeof 在结构体中的对齐:结构体大小可能大于各成员大小之和,因为存在内存对齐。
- 数组作为函数参数:数组作为函数参数时会退化为指针,此时
sizeof得到的是指针大小。
7. 总结
sizeof和strlen虽然都与“大小”相关,但设计目的完全不同:
sizeof:用于内存管理,计算数据类型或对象在内存中的字节数,编译时确定。strlen:用于字符串处理,计算 C 风格字符串的有效字符数,运行时遍历计算。
在实际编程中,应根据具体需求选择使用:需要内存分配、拷贝或计算结构大小时用sizeof;需要获取字符串长度进行遍历、比较或拼接时用strlen。理解它们的区别能帮助避免许多隐蔽的错误。