基于本文回答
0
评论

C++ sizeof 和 strlen 的区别?

知识点图片

在 C++(以及 C 语言)中,sizeofstrlen 是两个经常被放在一起比较的概念,尤其是在处理字符串和数组时。它们虽然常常用于获取“长度”或“大小”,但其本质、工作原理和应用场景完全不同

以下是它们的核心区别总结:

1. 核心对比速览

特性 sizeof strlen
本质 单目运算符 (Operator) 库函数 (Function)
计算时机 编译时(绝大多数情况) 运行时
功能 计算数据类型或变量所占的内存字节数 计算 C 风格字符串的字符长度
参数类型 任何数据类型、变量、对象、数组等 必须是以 \0 结尾的字符指针 (const char*)
\0 的处理 包含 \0 的空间(如果是字符数组) 不包含 \0,遇到 \0 即停止计算
所属头文件 属于 C++ 核心语法,不需要头文件 需要引入 <cstring><string.h>

2. 详细解析与代码示例

(1) sizeof:内存的“测量尺”

sizeof 关心的是在内存中分配了多少空间。因为它通常在编译时计算,所以它不会去读取变量里面的具体内容。

cpp
char arr[100] = "hello";
cout << sizeof(arr);  // 输出 100。因为数组声明了 100 个字节的空间。

char str[] = "hello";
cout << sizeof(str);  // 输出 6。因为 "hello" 有 5 个字母,加上隐藏的结束符 '\0',共占用 6 个字节。

int num = 10;
cout << sizeof(num);  // 输出 4(在大多数 32/64 位系统上,int 占 4 字节)。

(2) strlen:字符串的“计步器”

strlen 关心的是字符串里有多少个有效字符。它的工作原理是从给定的内存地址开始往后遍历,直到遇到第一个 \0(ASCII 码为 0 的字符)才停止,并返回遍历经过的字符个数。

cpp
#include <cstring>

char arr[100] = "hello";
cout << strlen(arr);  // 输出 5。它只数到 'o',遇到 '\0' 就停了,不管数组实际有多大。

char str[] = "hello";
cout << strlen(str);  // 输出 5。同样不包含 '\0'。

char badStr[5] = {'h', 'e', 'l', 'l', 'o'}; // 注意:这里没有空间放 '\0'
// cout << strlen(badStr); // 危险操作!它会越界读取,直到在内存其他地方碰巧遇到 '\0',返回一个不可预知的垃圾值。

3. 最容易踩坑的场景:数组退化为指针

这是面试中最常考的陷阱。当把数组名赋给指针,或者将数组作为参数传递给函数时,数组会“退化”为指针。

cpp
char str[] = "hello";
char* ptr = str;

// sizeof 的区别
cout << sizeof(str); // 输出 6(计算整个字符数组的大小)
cout << sizeof(ptr); // 输出 8 或 4(计算指针变量本身的大小,64位系统为8字节,32位系统为4字节)

// strlen 的表现一致
cout << strlen(str); // 输出 5
cout << strlen(ptr); // 输出 5

函数参数传值的陷阱:

cpp
void test(char arr[]) {
    // 这里的 arr 看似是数组,其实已经被编译器隐式转换为了指针 char*
    cout << sizeof(arr) << endl; // 输出 8 (或4),而不是数组原本的大小!
    cout << strlen(arr) << endl; // 输出字符串的实际长度
}

int main() {
    char str[100] = "hello";
    test(str);
    return 0;
}

4. 总结与现代 C++ 建议

  • sizeof:当你需要知道一个类型、结构体、类或静态数组在内存中占用多少字节时(例如在调用 memsetmemcpy 或进行底层内存分配时)。
  • strlen:当你处理 C 风格字符串(char*),并且需要知道它包含多少个可见字符时。

🌟 现代 C++ 最佳实践:
在现代 C++ 中,强烈建议尽量减少 C 风格字符串(char*strlen)的使用,转而使用:

  1. std::string:直接使用 str.length()str.size() 获取长度,安全且高效。
  2. std::size() (C++17):用于安全地获取数组的元素个数,如果传入退化的指针会在编译时报错,避免了 sizeof 计算数组长度时的潜在 Bug。
  3. std::string_view (C++17):用于替代只读的 const char*,自带长度信息,无需像 strlen 那样每次遍历计算。
右滑查看面试常问