C语言字符串与sizeof解析

📋 速记

  • sizeof 是关键字,用来计算对象或类型占用的字节数。
  • C 语言字符串本质是以 \0 结尾的 char 数组。
  • sizeof(arr) / sizeof(arr[0]) 可以计算数组元素个数。
  • 数组传参后会退化为指针,因此长度通常需要单独传入。
  • 统计字符串字符个数时,应使用 strlen,而不是 sizeof
💡 记忆口诀
sizeof 算内存,strlen 数字符;数组退指针,长度要传入。

一、C语言字符串的本质:char 数组

C 语言没有真正的 string 类型。所谓字符串,本质上是一个以 '\0' 结尾的 char 序列。实际开发中,常见写法主要有两种:字符数组,以及指向字符串常量的字符指针。如果只是读取字符串字面量,更推荐写成 const char *

1.1 两种形式

// 形式一:字符数组(可修改)
char str[] = "Hello";

// 形式二:指向字符串常量的指针(推荐)
const char *str = "Hello";
形式 本体 存储位置 能否修改
char str[] = "Hello"; 数组 数组元素在栈上 ✅ 可以
const char *str = "Hello"; 指针 指针在栈上,字符串常量在只读区 ❌ 不可以

1.2 字符数组为什么本质是 char 数组

// 这两种写法完全等价
char str1[] = "Hello";
char str2[] = {'H', 'e', 'l', 'l', 'o', '\0'};

内存中的样子如下:

地址:    0     1     2     3     4     5
       ['H'] ['e'] ['l'] ['l'] ['o'] ['\0']
         ↑ ——————— char 数组 ——————————↑ 结束标志

1.3 为什么字符串常量前最好加 const

const char *ptr = "Hello";   // 推荐写法
// ptr[0] = 'h';              // ❌ 不能通过 ptr 修改字符串常量

如果写成 char *ptr = "Hello";,有些编译器也许还能通过,但这属于不推荐写法。因为 "Hello" 通常存放在只读区域,一旦修改就会触发未定义行为。

⚠️ 推荐写法:指针如果只是指向字符串常量,请写成 const char *ptr = "Hello";。如果你需要修改内容,就用 char arr[] = "Hello";

二、C语言 sizeof 到底是什么?

C语言 sizeof 是关键字,不是函数。它的作用是获取某个类型或对象所占的字节数

printf("%zu\n", sizeof(int));
printf("%zu\n", sizeof(char));
printf("%zu\n", sizeof(double));

sizeof

ℹ️ 关键点sizeof 的结果通常在编译阶段就能确定,返回类型是 size_t。它不是像 strlen 那样在运行时遍历字符串的函数。

2.1 sizeof 作用在字符串上时得到什么

char str[] = "Hello";
printf("%zu\n", sizeof(str));  // 6

这里的结果是 6,不是 5,因为数组里除了 'H''e''l''l''o' 之外,还包含结尾的 '\0'

⚠️ 注意"Hello" 是 5 个可见字符,但 sizeof(str) 是 6,因为数组里还要存结束标志 '\0'

2.2 strlensizeof 的区别

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello";

    printf("sizeof(str) = %zu\n", sizeof(str));  // 6
    printf("strlen(str) = %zu\n", strlen(str));  // 5

    return 0;
}
对比项 sizeof strlen
本质 关键字 函数
计算时机 编译期可确定 运行时统计
是否包含 \0 ✅ 包含 ❌ 不包含
参数 类型或变量 字符串首地址

三、sizeof(arr)/sizeof(arr[0]) 为什么能算数组长度?

这是 C 语言里计算数组元素个数的标准写法。原因很简单:C 语言没有 arr.length 这种内置属性,所以只能用 总大小 ÷ 单个元素大小 的方式自己算。

int arr[] = {1, 2, 3, 4, 5};
int count = sizeof(arr) / sizeof(arr[0]);  // count = 5
sizeof(arr)     // 整个数组的字节数
sizeof(arr[0])  // 单个元素的字节数

如果 int 占 4 字节,那么:

sizeof(arr)     // 20
sizeof(arr[0])  // 4
20 / 4 = 5

3.1 为什么不直接写死数字

// ❌ 硬编码,数组一改就容易出错
for (int i = 0; i < 5; i++) {
    // ...
}

// ✅ 自动计算,数组变化时循环自动适配
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
    // ...
}
💡 一句话理解
sizeof(arr) / sizeof(arr[0]) 本质上就是数学里的“总量 ÷ 单量 = 数量”。

四、C语言 sizeof 的常见陷阱

4.1 数组作为函数参数会退化为指针

void print_size(int arr[]) {  // 等价于 int *arr
    printf("%zu\n", sizeof(arr));
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    printf("%zu\n", sizeof(arr));  // 20
    print_size(arr);                 // 8
    return 0;
}

在函数参数位置,数组会退化成指针。因此 sizeof(arr) 拿到的不是整个数组大小,而只是指针大小。

⚠️ 核心规则:数组一旦作为函数参数传入,sizeof 就无法再帮你算出元素个数。正确做法是把长度一起传进去。
void process(int arr[], int len) {
    for (int i = 0; i < len; i++) {
        // ...
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int len = sizeof(arr) / sizeof(arr[0]);
    process(arr, len);
    return 0;
}

4.2 对指针使用 sizeof 得到的不是字符串长度

char *ptr = "Hello";
printf("%zu\n", sizeof(ptr));  // 8

char arr[] = "Hello";
printf("%zu\n", sizeof(arr));  // 6
写法 sizeof 结果 原因
char arr[] = "Hello"; 6 arr 是数组,包含 \0
char *ptr = "Hello"; 8 ptr 是指针,只保存地址

4.3 字符串长度应该用 strlen

char *ptr = "Hello";

// ❌ 错误
int len1 = sizeof(ptr);

// ✅ 正确
int len2 = strlen(ptr);
ℹ️ 区分方法:想知道“占多少字节”用 sizeof,想知道“有多少个字符”用 strlen

五、字符串数组遍历示例

#include <stdio.h>

int main() {
    char *fruits[] = {"苹果", "香蕉", "橙子", "葡萄"};
    int count = sizeof(fruits) / sizeof(fruits[0]);

    printf("共有 %d 种水果:\n", count);
    for (int i = 0; i < count; i++) {
        printf("  %d. %s\n", i + 1, fruits[i]);
    }

    return 0;
}

输出结果:

共有 4 种水果:
  1. 苹果
  2. 香蕉
  3. 橙子
  4. 葡萄

5.1 这个例子为什么能算对

char *fruits[] = {"苹果", "香蕉", "橙子", "葡萄"};

sizeof(fruits)      // 32,4 个指针 × 8 字节
sizeof(fruits[0])   // 8,单个指针大小
32 / 8 = 4
💡 补充说明
这里算出来的是“数组里有几个元素”,也就是有几个指针,而不是每个字符串内部有多少个字符。

六、C语言 sizeof 速查表

6.1 常见类型的 sizeof

类型 sizeof
char 1
short 2
int 4
long 8
float 4
double 8
指针(任意类型) 8

6.2 字符串相关的 sizeof

代码 sizeof 结果 说明
char s[] = "Hi"; 3 数组,包含 \0
char s[] = "Hello"; 6 数组,包含 \0
const char *p = "Hello"; 8 指针大小
char s[10] = "Hi"; 10 数组总大小固定为 10

七、相关阅读与延伸阅读

8.1 相关阅读

8.2 延伸阅读