关于C语言中静态与动态数组指针算术访问机制的疑问
关于C语言中静态与动态数组指针算术访问机制的疑问
嘿,这个问题问到点子上了,很多刚啃C语言指针的朋友都会在这儿绕晕,我给你掰开揉碎讲清楚:
首先得把**静态数组名a和指针变量b**的本质差异搞透,这是解开疑惑的核心:
- 静态数组的名字
a,它不是一个变量,而是编译阶段就确定好的地址常量。说白了,编译器在编译代码时,直接把a替换成了数组首元素的内存地址,这个值是固定死的——你甚至没法写a = a + 1,这在C里是非法的,因为常量不能被修改。 - 而
b是个实打实的指针变量,它自己占了一块内存(比如64位系统里是8字节),里面存的是malloc分配的动态数组的首地址。它是可以被修改的,比如你写b = b + 1完全合法,之后b就指向数组的第二个元素了。
现在拆解你疑惑的两个表达式:
先看*(a + 9)
- 编译器看到
a,直接用它对应的编译期常量地址(数组首元素地址),根本不需要去内存里读任何值。 - 接着做指针算术:
a + 9会自动转换成a + 9 * sizeof(int)(比如int占4字节,就是加36),得到数组第10个元素的地址。 - 最后用
*解引用这个地址,取出里面的9。
再看*(b + 9)
- 编译器看到
b,首先会去读取这个指针变量内部存储的内容——也就是malloc给你的动态数组的首地址,这一步是程序运行时才做的,因为malloc的地址是程序跑起来后分配的。 - 然后用这个读出来的地址做指针算术,同样加上
9 * sizeof(int),得到目标元素的地址。 - 最后
*解引用这个地址,取出对应的值。
你说的“b被读取为变量b里存储的地址”,这个理解完全正确!而a根本不需要读内存,它本身就是编译器硬编码进程序里的地址常量。
再补个直观对比:
- 你可以写
&a,得到的是整个数组的地址(类型是int (*)[10]),它的值和a是一样的,只是类型不同;但&b得到的是指针变量b自己的地址(类型是int**),和b里面存的动态数组地址完全不是一回事。
C语言这么设计,其实是为了语法一致性——让你能用同样的指针算术语法访问静态和动态数组,不用记两套规则,但本质上数组名和指针变量是完全不同的东西哦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

