卡码笔记-最强八股文
首页
计算机基础
C++
Java
Go
大模型
  • Java面经
  • C++面经
  • 大模型面经
简历专栏
代码随想录 (opens new window)
首页
计算机基础
C++
Java
Go
大模型
  • Java面经
  • C++面经
  • 大模型面经
简历专栏
代码随想录 (opens new window)
  • 基础与语法

    • 介绍c++一下三大特性
    • 指针和引用的区别
    • 结构体和类的区别
    • 结构体与联合体的区别
    • static关键字和const关键字的作用
    • extern C的作用
    • volatile关键字的作用
    • inline函数与宏的区别与优劣
    • auto和decltype的区别
    • sizeof和strlen的区别
      • 简要回答
      • 详细回答
      • 代码示范
      • 知识拓展:面试官的追问
    • 浮点数比较方法
    • 静态局部变量,全局变量,局部变量的特点,以及使用场景
    • C++中四种类型转换
  • 面向对象

  • STL 与容器

  • 内存管理

  • C++11 与现代 C++

  • 智能指针

  • 并发与 I/O

# sizeof 和 strlen 的区别

# 简要回答

一句话概括:sizeof 是编译期运算符,计算的是类型或变量占用的内存字节数;strlen 是运行时函数,计算的是字符串中 \0 之前的字符个数。两者都能作用于字符串,但结果不同,含义也不同。


# 详细回答

理解这两者的本质区别,要从它们各自"看"字符串的角度出发。

两者的核心差异对比:

对比维度 sizeof strlen
本质 运算符(operator) 标准库函数(<cstring>)
执行时机 编译期(compile-time) 运行时(runtime)
计算内容 类型/变量占用的字节数 \0 前的字符个数
包含 '\0'? 包含 不包含
适用类型 任意类型(int、struct…) 仅限 char* / char[]

# 代码示范

#include <iostream>
#include <cstring>
using namespace std;

int main() {

    // ── 情况1:字符数组 ──────────────────────────
    char s1[] = "hello";
    cout << sizeof(s1) << endl;  // 6,数组大小 = 5字符 + 1个'\0'
    cout << strlen(s1) << endl;  // 5,不含'\0'

    // ── 情况2:字符指针 ──────────────────────────
    const char* s2 = "hello";
    cout << sizeof(s2) << endl;  // 8(64位系统指针大小),不是字符串长度!
    cout << strlen(s2) << endl;  // 5,正常计算

    // ── 情况3:手动指定大小的数组 ──────────────────
    char s3[20] = "hello";
    cout << sizeof(s3) << endl;  // 20,数组声明的总大小
    cout << strlen(s3) << endl;  // 5,只看'\0'之前

    // ── 情况4:sizeof 用于非字符串类型 ─────────────
    cout << sizeof(int)    << endl;  // 4
    cout << sizeof(double) << endl;  // 8
    // strlen(42); // ❌ 编译错误:strlen 只接受 char*

    // ── 情况5:含中间'\0'的字符数组(经典陷阱)──────
    char s4[] = {'a', '\0', 'b', 'c'};
    cout << sizeof(s4) << endl;  // 4,数组真实大小
    cout << strlen(s4) << endl;  // 1,碰到第一个'\0'就停了!

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

输出结果:

6
5
8
5
20
5
4
8
4
1
1
2
3
4
5
6
7
8
9
10

情况5是最容易踩坑的地方:sizeof 如实返回4,但 strlen 只返回1,因为它在第二个字节就遇到了 \0 并停止了遍历。


# 知识拓展:面试官的追问

# 追问1:sizeof 对指针和数组有什么区别?

这是最高频的追问,也是最容易答错的。

char arr[] = "hello";   // 栈上的数组
char* ptr  = "hello";  // 指向字符串字面量的指针

sizeof(arr);  // 6 —— sizeof 看到的是整个数组 char[6]
sizeof(ptr);  // 8 —— 指针本身的大小,与字符串长度无关
1
2
3
4
5

核心原因:sizeof 是编译期运算符,直接查看类型信息。arr 的类型是 char[6],返回6;ptr 的类型是 char*,返回指针大小(64位系统为8字节)。


# 追问2:数组作为函数参数传递时,sizeof 还准确吗?

不准确,这是一个经典陷阱:

void foo(char arr[]) {
    cout << sizeof(arr) << endl;  // 输出 8!不是数组大小
    // char arr[] 作为参数等价于 char* arr,数组退化成了指针
}

int main() {
    char s[] = "hello";
    cout << sizeof(s) << endl;  // 6,正确
    foo(s);                     // 传进去就退化了
}
1
2
3
4
5
6
7
8
9
10

数组一旦作为函数参数传递,就退化为指针,sizeof 只能得到指针大小。如果需要在函数内知道数组长度,必须额外传一个 len 参数。


# 追问3:strlen 的时间复杂度是多少?能优化吗?

strlen 是 O(n) 的,本质上是从头遍历到 \0:

// strlen 的等价实现
size_t my_strlen(const char* s) {
    const char* p = s;
    while (*p != '\0') p++;
    return p - s;
}
1
2
3
4
5
6

如果在循环中反复调用 strlen,要把结果缓存起来:

// ❌ 差写法:每次循环都重新遍历
for (int i = 0; i < strlen(s); i++) { ... }

// ✓ 好写法:提前缓存长度
size_t len = strlen(s);
for (int i = 0; i < len; i++) { ... }
1
2
3
4
5
6

# 追问4:sizeof 的结果一定是编译期常量吗?

在标准 C++ 中,是的。但 C99 引入了变长数组(VLA),在 C 语言中 sizeof 会退化为运行时计算:

// C语言(不是C++)
void foo(int n) {
    int arr[n];                        // VLA,大小运行时才确定
    printf("%zu\n", sizeof(arr));      // 运行时求值,不是编译期常量
}
1
2
3
4
5

C++ 标准不支持 VLA,所以在标准 C++ 中 sizeof 的结果始终是编译期常量。


Last Updated: 2026/4/8 16:09:35

← auto和decltype的区别 浮点数比较方法 →

评论

验证登录状态...

侧边栏
夜间
卡码简历
代码随想录
卡码投递表🔥
2026群
添加客服微信 PS:通过微信后,请发送姓名-学校-年级-2026实习/校招
支持卡码笔记
鼓励/支持/赞赏Carl
1. 如果感觉本站对你很有帮助,也可以请Carl喝杯奶茶,金额大小不重要,心意已经收下
2. 希望大家都能梦想成真,有好的前程,加油💪