sizeof 是一个 C 语言中的单目运算符,而不是函数,它的作用是返回一个对象或类型所占的内存字节数。

(图片来源网络,侵删)
当 sizeof 用于数组时,它返回的是整个数组在内存中所占的总字节数。
基本用法:sizeof(数组名)
这是最核心的用法。sizeof 会计算数组所有元素占用的内存总和。
示例代码:
#include <stdio.h>
int main() {
// 1. 整型数组
int arr_int[5] = {10, 20, 30, 40, 50};
// sizeof(int) 通常是 4 字节
// sizeof(arr_int) = 5 * 4 = 20 字节
printf("int arr_int[5] 的大小是: %zu 字节\n", sizeof(arr_int)); // 输出 20
// 2. 字符数组
char arr_char[10] = "Hello";
// sizeof(char) 通常是 1 字节
// sizeof(arr_char) = 10 * 1 = 10 字节 (注意:这里计算的是整个数组的大小,包括预留的空间)
printf("char arr_char[10] 的大小是: %zu 字节\n", sizeof(arr_char)); // 输出 10
// 3. 双精度浮点型数组
double arr_double[3];
// sizeof(double) 通常是 8 字节
// sizeof(arr_double) = 3 * 8 = 24 字节
printf("double arr_double[3] 的大小是: %zu 字节\n", sizeof(arr_double)); // 输出 24
return 0;
}
关键点:

(图片来源网络,侵删)
sizeof(数组名)得到的是整个数组的大小。- 结果可以通过
元素个数 * sizeof(元素类型)来验证。 %zu是size_t类型的正确格式说明符,因为sizeof的返回值类型是size_t。
sizeof 与数组名的重要区别
这是最容易出错的地方,当数组名不作为 sizeof 的操作数时,它通常会“退化”(decay)为指向数组首元素的指针。
示例代码:
#include <stdio.h>
int main() {
int arr[10] = {0};
printf("sizeof(arr) = %zu\n", sizeof(arr)); // 输出 40 (整个数组的大小)
// 当数组名用于其他地方(如 &arr, arr+i),它会退化
int *p = arr; // 等价于 int *p = &arr[0];
printf("arr 的地址: %p\n", (void*)arr);
printf("&arr[0] 的地址: %p\n", (void*)&arr[0]);
printf("p 的地址: %p\n", (void*)p);
// 三个地址打印出来是一样的
// 关键区别在这里:
printf("sizeof(p) = %zu\n", sizeof(p)); // 输出 4 或 8 (取决于系统,是指针的大小)
// p 是一个指针变量,它存储的是地址,sizeof(p) 是指针本身的大小,
// 而不是它指向的数组的大小。
return 0;
}
| 表达式 | 含义 | 结果(假设 int 是4字节,指针是8字节) |
| :--- | :--- | :--- |
| sizeof(数组名) | 数组占用的总字节数 | 40 (int arr[10]) |
| 数组名 (非 sizeof 场合) | 退化为指向首元素的指针 | &arr[0] (一个地址值) |
| sizeof(数组名 + 0) | sizeof(一个指针) | 8 (指针的大小) |
| sizeof(&数组名) | sizeof(一个指向数组的指针) | 8 (指针的大小) |
作为函数参数的数组
当数组作为函数参数传递时,它会自动退化为指向其首元素的指针,这是 C 语言的一个核心规则。

(图片来源网络,侵删)
示例代码:
#include <stdio.h>
// 这个函数无法通过 sizeof 获取数组真实大小
void print_array_size(int arr_param[], int size) {
// 在函数内部,arr_param 实际上是一个 int* 指针
// sizeof(arr_param) 得到的是指针的大小,而不是数组的大小
printf("在函数内部,sizeof(arr_param) = %zu\n", sizeof(arr_param)); // 输出 8 (64位系统)
// 必须通过另一个参数来传递数组的大小
printf("通过参数传递的数组大小是: %d\n", size);
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("在 main 函数中,sizeof(arr) = %zu\n", sizeof(arr)); // 输出 20
// 调用时,只传递了数组名(它退化为指针)和它的真实大小
print_array_size(arr, 5);
return 0;
}
重要结论:
- 你无法在函数内部通过
sizeof来获取传递过来的数组的大小。 - 如果函数需要知道数组的大小,必须额外传递一个
size参数。 - 这就是为什么 C 标准库函数(如
strcpy,memcpy)要么需要一个长度参数,要么需要一个特殊的结束标记(如'\0'用于字符串)。
sizeof 与多维数组
sizeof 对于多维数组同样有效,它会计算所有维度元素的总大小。
示例代码:
#include <stdio.h>
int main() {
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// sizeof(matrix) = 3行 * 4列 * sizeof(int) = 3 * 4 * 4 = 48 字节
printf("sizeof(matrix) = %zu\n", sizeof(matrix)); // 输出 48
// 当只指定第一维时,它不会退化,而是表示一个“数组指针”
// sizeof(matrix[0]) 计算的是第一行的大小 (4个int)
printf("sizeof(matrix[0]) = %zu\n", sizeof(matrix[0])); // 输出 16
// sizeof(matrix[0][0]) 计算的是单个元素的大小
printf("sizeof(matrix[0][0]) = %zu\n", sizeof(matrix[0][0])); // 输出 4
// 可以推导出行数和列数
int rows = sizeof(matrix) / sizeof(matrix[0]);
int cols = sizeof(matrix[0]) / sizeof(matrix[0][0]);
printf("矩阵的行数: %d\n", rows); // 输出 3
printf("矩阵的列数: %d\n", cols); // 输出 4
return 0;
}
sizeof 与变长数组 (VLA - Variable Length Array)
C99 引入了变长数组,其大小在运行时确定。sizeof 对于 VLA 也是在编译时计算(如果编译器支持 VLA 优化),或者在运行时计算。
示例代码:
#include <stdio.h>
void calculate_vla_size(int n) {
// VLA 的大小由函数参数 n 决定
int vla[n];
printf("在函数内部,n = %d\n", n);
// 对于 VLA,sizeof(vla) 在编译时可能无法确定,编译器会生成代码在运行时计算
printf("sizeof(vla) = %zu\n", sizeof(vla)); // 输出 n * sizeof(int)
}
int main() {
int size = 10;
int vla_main[size];
printf("在 main 函数中,sizeof(vla_main) = %zu\n", sizeof(vla_main)); // 输出 40
calculate_vla_size(5);
return 0;
}
注意: VLA 是 C99 的特性,但并非所有编译器都完全支持或默认开启,C11 标准将 VLA 设为可选特性。
总结表格
| 场景 | sizeof 行为 |
结果 |
|---|---|---|
在作用域内 sizeof(数组名) |
计算整个数组的总字节数 | 元素个数 * sizeof(元素类型) |
作为函数参数 sizeof(数组名) |
数组名退化为指针,计算指针的大小 | sizeof(指针类型) (通常是 4 或 8 字节) |
在作用域内 数组名 (非 sizeof) |
退化为指向首元素的指针 | &arr[0] (地址) |
多维数组 sizeof(数组名) |
计算所有元素的总字节数 | 行数 * 列数 * sizeof(元素类型) |
变长数组 (VLA) sizeof(数组名) |
计算数组的总字节数(可能在运行时计算) | 运行时确定的元素个数 * sizeof(元素类型) |
核心要点:
sizeof(数组名)是获取数组大小的唯一可靠方式,且必须在数组定义的作用域内使用。- 数组名在大多数情况下会退化为指针,
sizeof作用于指针得到的是指针本身的大小,而不是它指向的数据的大小。 - 函数无法通过
sizeof获取传递过来的数组的大小,必须额外传递大小参数。
