 和 sizeof(ptr) 不一样?)
数组名和指针90%的人都分不清为什么 sizeof(arr) 和 sizeof(ptr) 不一样有没有遇到过这种情况#includestdio.hintmain(){intarr[10]{0};int*ptrarr;printf(sizeof(arr) %zu\n,sizeof(arr));// 输出 40printf(sizeof(ptr) %zu\n,sizeof(ptr));// 输出 864位或 432位return0;}很多刚学C语言的人看到这个输出就懵了“arr 和 ptr 不都是指向数组首元素的吗为什么 sizeof 结果不一样”有人甚至会因此写出错误的代码——把数组当参数传给函数后想在函数里用 sizeof 算数组长度结果死活不对。今天用 5 分钟把这个坑彻底填上。一句话结论数组名不等于指针arr是数组名代表整个数组。ptr是指针变量存的只是数组首元素的地址。所以sizeof(arr) 整个数组占用的字节数 10 × 4 40sizeof(ptr) 指针变量本身占用的字节数 864位系统画个图就清楚了假设 arr 在内存中长这样arr: ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘ 0x1000 0x1028 sizeof(arr) → 从 0x1000 到 0x1028总共 40 字节ptr 只存了一个地址ptr: ┌──────────┐ │ 0x1000 │ ← 8 字节64位系统 └──────────┘ sizeof(ptr) → 8 字节指针变量的大小arr 是一整块地ptr 只是一个门牌号。什么时候数组名会退化成指针大多数情况下数组名会被自动转换成指向首元素的指针。这个操作叫数组到指针的隐式转换decay。intarr[10];// 这些地方 arr 会退化int*parr;// ✅ arr 变成 arr[0]func(arr);// ✅ 传参时退化arr1;// ✅ 参与运算时退化但sizeof 不会让它退化。sizeof 是一个特殊的编译时运算符它看到的 arr 就是数组本身因为它知道完整的类型信息。除了 sizeof还有一个地方数组名不退化intarr[10];int(*p)[10]arr;// arr 不会退化拿到的是数组的地址arr的类型是int (*)[10]指向包含 10 个 int 的数组的指针而不是int **。为什么传参时 sizeof 又不对了这是最坑的地方。看这段代码voidfunc(intarr[]){printf(sizeof(arr) %zu\n,sizeof(arr));// 输出 8不是 40}intmain(){intarr[10]{0};func(arr);return0;}为什么在 func 里 sizeof(arr) 变成 8 了因为函数参数里的数组写法本质上就是指针voidfunc(intarr[])// 等价于 ↓voidfunc(int*arr)// 这才是真相编译器看到int arr[]当形参时直接给你换成int *arr。所以 func 里的 arr 已经不是数组名了而是一个指针变量。这就是为什么在函数里用sizeof(arr) / sizeof(arr[0])算数组长度会翻车。正确的做法是把长度也传进去voidfunc(int*arr,size_tlen){for(size_ti0;ilen;i){printf(%d ,arr[i]);}}一张表总结场景arr 是什么sizeof(arr) 结果在定义它的函数内数组整个数组的大小传给函数后指针退化指针变量大小8字节arr数组地址指针变量大小arr 0首元素地址指针变量大小记住一句话sizeof 能看到数组是因为编译器知道它的完整类型。一旦数组离开定义它的作用域——不管是传参、赋值给指针、还是参与运算——它就退化成了指针sizeof 再也看不到原来的大小了。下次再碰到 sizeof 对数组失灵的情况回来查这张表就行。你还在哪些场景被数组和指针坑过评论区聊聊下期可以专门讲。#C语言 #sizeof #指针 #数组 #编程避坑