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

猜你喜欢

转载自blog.csdn.net/qq2071114140/article/details/87927824