You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中数组变量的存储机制(聚焦命名变量中的指针而非内存)

C数组与指针的核心差异:为什么sizeof有时有效有时失效

首先明确:C语言里的数组既不是普通指针,也不是带长度的宽指针。你的困惑来自C数组的特殊设计——数组退化,以及编译期与运行期的信息差异。

1. 数组变量的本质:编译期已知的连续内存块

当你写int arr[5];时,编译器会:

  • 在栈或全局区分配一块能装下5个int的连续内存
  • 给这块内存绑定名字arr
  • 编译期就记住arr的长度是5,所以sizeof(arr)会直接被替换成5 * sizeof(int)——这是编译期计算的常量,不需要运行时额外存储长度信息

这和Rust的[i32; 5]有相似性,但C的数组长度不是类型的一部分:你没法让函数参数明确是int arr[5](编译器会直接把它当成指针),而Rust的数组长度是类型的一部分,fn func(arr: [i32;5])是完全明确的。

2. 为什么数组看起来和指针像?——隐式退化

在绝大多数表达式场景下,数组名会自动转换为指向首元素的指针,比如:

int arr[5];
int *p = arr; // 等价于 int *p = &arr[0];

这种转换就是“数组退化”,也是你觉得char argv[][]和char **argv能互换的原因——但这只是语法相似,底层逻辑完全不同:

  • char argv[3][4]是一块连续的12个char的内存,argv[i][j]等价于*(argv + i*4 + j)
  • char **argv是一个指针,指向多个独立的char*指针,每个指针又指向单独的char数组,argv[i][j]等价于*(*(argv + i) + j)

3. 函数传参后sizeof失效的原因:参数里的数组会完全退化为指针

C语言的函数参数中,数组类型会被直接解析为指针类型:

// 下面两个函数声明完全等价
void func(int arr[]);
void func(int *arr);

所以当你把数组传给函数时,实际上只传了首元素的地址,函数内部拿到的是一个指针,sizeof(arr)自然取的是指针的大小(比如64位系统是8字节),而非数组的总大小。

这是C早期的设计选择——为避免拷贝大数组(当年内存资源紧张),默认传首地址。如果要在函数里获取数组长度,必须手动把长度作为参数传入,比如:

void func(int *arr, int len);

4. 关于“宽指针”的疑问

C语言没有原生的宽指针(带长度的指针),但你可以手动模拟——比如用结构体存储指针和长度,这其实就是Rust里&[T]切片的底层逻辑,但C没有原生支持这种类型,所有长度信息都需要手动管理。

内容的提问来源于stack exchange,提问作者Mindustry Logic Processor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 05:42:20