C语言字符串与sizeof解析
- C语言进阶
- 14小时前
- 55热度
- 0评论
📋 速记
sizeof是关键字,用来计算对象或类型占用的字节数。- C 语言字符串本质是以
\0结尾的char数组。 sizeof(arr) / sizeof(arr[0])可以计算数组元素个数。- 数组传参后会退化为指针,因此长度通常需要单独传入。
- 统计字符串字符个数时,应使用
strlen,而不是sizeof。
💡 记忆口诀
sizeof 算内存,strlen 数字符;数组退指针,长度要传入。
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 的结果通常在编译阶段就能确定,返回类型是 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 strlen 与 sizeof 的区别
#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 |