深入理解C语言指针(五):sizeof、strlen与指针题解析

深入理解C语言指针(五):sizeof、strlen与指针题解析

1. sizeof与strlen

sizeof 是操作符,用于计算类型或对象占用的字节数;strlen 是库函数,用于统计字符串中 \0 之前的字符数。

1
2
3
char arr[] = "abc";
printf("%zu\n", sizeof(arr)); // 4,包含\0
printf("%zu\n", strlen(arr)); // 3
对比 sizeof strlen
性质 操作符 库函数
单位 字节 字符个数
终止条件 由类型和对象决定 遇到 \0
头文件 无需头文件 <string.h>

char arr[3] = {'a', 'b', 'c'}; 不是合法C字符串,调用 strlen(arr) 会越界查找 \0,属于未定义行为。

2. 数组名的两类语境

1
int arr[10];

多数表达式中 arr 转换为 int *,但以下情况表示整个数组:

1
2
sizeof(arr); // 整个数组大小
&arr; // 整个数组的地址,类型为int (*)[10]
1
2
3
printf("%zu\n", sizeof(arr));       // 10 * sizeof(int)
printf("%zu\n", sizeof(arr + 0)); // 指针大小
printf("%zu\n", sizeof(&arr)); // 指针大小

3. 字符数组与字符指针

1
2
char a[] = "hello";
const char *p = "hello";
  • a 是含有6个字符的数组,内容可修改;
  • p 是指针,保存字符串字面量地址,不应通过它修改内容;
  • sizeof(a) 是6;
  • sizeof(p) 是指针本身大小;
  • strlen(a) 和 strlen(p) 都是5。

4. 指针运算分析

1
2
int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;
1
2
3
*(p + 2)      // 30
p[2] // 30
&arr[2] - p // 2

指针加减的单位是所指向类型的大小。只有指向同一数组及尾后位置的指针,才适合进行相减和有序比较。

5. 二维数组分析

1
int matrix[3][4];
  • matrix 多数情况下转换为 int (*)[4];
  • matrix + 1 跳过一整行;
  • *matrix 是第0行,并进一步转换为 int *;
  • *(*(matrix + i) + j) 等价于 matrix[i][j];
  • sizeof(matrix) 是整个二维数组大小。

6. 做题方法

遇到复杂表达式时按顺序分析:

  1. 确定变量原始类型;
  2. 判断数组名是否发生退化;
  3. 判断指针每次移动的跨度;
  4. 从内向外处理括号、解引用和下标;
  5. 判断指针是否仍在合法对象范围内;
  6. 最后确定 sizeof 求的是对象还是指针。

7. 易错点

  • 使用 %d 输出 size_t,应使用 %zu;
  • 对没有 \0 的字符数组调用 strlen;
  • 把地址数值相同误认为指针类型相同;
  • 对越界指针解引用;
  • 在函数形参中误用 sizeof(arr) 求调用者数组长度。

8. 总结

数组指针题并非靠背答案。只要抓住类型、退化规则、步长和对象边界,就能把复杂表达式拆解为可验证的步骤。