C语言指针和数组的不同
C语言的指针和数组不是一个东西(⊙o⊙)
这篇文章只要是想说一下在进行下标(地址偏移)的时候,误将指针和数组看作一个东西,发生一些微妙的错误
一.通过一个例子来引入话题
源文件1内容:
int a[5] = {1, 2, 3, 4, 5};
int *b = a;
源文件2内容:
#include <stdio.h>
extern int *a;
extern int b[];
int main(void){
printf("%d %d", a[4], b[4]);
return 0;
}
预测一下输出结果,输出的是两个5吗?
运行一下看下结果是否和猜测一致吧
竟然出错了
二.指针变量和数组在计算偏移量时的不同:
指针变量计算偏移量,首先会取出变量中存储的地址,与偏移量计算
数组计算偏移量,数组首地址(数组名)与偏移量进行计算
分析:
首先,从main()函数开始执行,要输出a[4],和b[4]。
先来讨论a[4]出错的原因
从源文件2的声明来看,a是一个指针变量,a[4]也就是*(a + 4),对于指针变量来说,需要这个指针变量存储的值在加上偏移量4×sizeof(int)。即,地址为a + 4指向的空间,但是这只是编译器一厢情愿的结果。
a是在源文件1中定义的,a是一个数组首地址,编译器把a当作一个指针变量,即把地址为a的这个空间存的值当作地址,a[4]的值就成了*(a[0] + 4); 如果上面说的有点迷,那下面用图来解释一下
由于a是a[0]的地址,但是源文件2的声明告诉编译器a是一个指针变量,对指针变量进行运算,首先要取出指针变量存的地址,所以在计算过程中,把a[0]当作了数组的首地址计算了偏移量。
来证明一下:编译器将a当作变量,计算时使用了a[0]的值
将输出语句改成printf("a = %d", a) 输出结果如下:
可见,编译器的确将a当作指针变量,计算的时候使用了它存储的值。b[4]出错原因:
源文件2声明了b是一个数组,计算偏移量的时候,会用b所在的空间的地址当作数组首地址,本应该用b中存储的值,但是却用了b的地址。
三.总结原因:
主要的原因就是它们偏移量计算方法不同。
计算数组的偏移量的时候,本应该用变量的地址,却用了变量存储的值
计算指针变量的偏移量的时候,本应该用变量存储的值,却用了变量的地址
由于地址计算出了问题,所以两个输出都会因为“越界”出错。
四.推论及证明
如果上述总结没有说服读者朋友,我们可以通过上述得结论得到一个推论:源文件1中的a(数组首地址)存储在b中,在源文件2中,b[0]的存储的值是a
证明一下:在源文件1中添加一个函数
int *f(void){
return a;
}//返回源文件1中的a(a是数组首地址)
将源文件2中主函数中的输出语句进行修改
int main(void){
printf("%d, %d", f(), *b);
return 0;
}
b被当作了一个数组的首地址,所以要取它存储的值(a),就要间接访问
2019/2/26 15:32:43