c语言指针的等式关系,c语言数组与指针浅析

大部分人,特别是初学者对于一些奇怪的数组表达式表示诧异。

举个例子:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#includeint main(void)

{

int a[3];

for(int i = 0; i<3; ++i)

{

*(a+i) = i+1;

}

//what is this ?! Are you kidding me ?!

//----------------------

printf("%d\n",*(a));

printf("%d\n",0[a+1]);

printf("%d\n",((*a)[a+1]));

return 0;

}

恩,很复杂,很无聊,感觉这样来表达根本没有意义。我也承认,把故意把它复杂化了,目的是讲清楚一些有关数组与指针的关系。

上面的程序,运行结果是把数组元素顺序输出,也就是分别输出1,2,3。

先来看看数组的定义:int a[3];

a 是数组名,相信大家都有过数组名 a 作为函数实参的经历,也就是把数组首元素地址 &a[0] 传给函数。这说明什么,说明数组名 a 一个指针,默认指向了数组的第一个元素 a[0]。

那么 a 作为指针,*a 是什么也就清楚了,*a 可以说是数组第一个元素的引用,也就是说,

*a = a[0]。以此类推 *(a+1) = a[1]……

明白这个之后,再来看看下面这个推导“公式”。

*a = *(a+0) = a[0] = *(0+a) = 0[a];

*(a+1) = a[1] = *(1+a) = 1[a];

这些表达式都是对的,a[i] = i[a] 也是成立的。再看看下面的推导:

*(a+1+1) = a[2] = *(1+a+1) = 1[a+1];

所以,a[2] = 1[a+1] 成立。可以这样来想,(i)[a+j] = a[i+j];

通过以上说明,对c语言数组与指针的关系可能更加清晰了。很多时候,我们会自己另外定义指针来指向数组:

1

2

3

4

5

6

int *p;

int a[3];

p = a; //从这里可以看出,a 就是一个指针

//有些人这样定义也对

p = &a[0];

p = &(*(a));

通过自己另外定义的指针来对数组进行操作,然而低调的数组名 a ,却淡然于世外,被人遗忘。

所以,回头看看一开始的那个程序,一切也就明白了,核心就是:数组名就是一个指针,默认指向了数组的首元素。所以,你对数组名的任何指针式的操作都是合法的。

上面是一维数组的操作,下面来说说二维数组。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

#includeint main(void)

{

int a[2][2];

a[0][0] = 1;

a[0][1] = 2;

a[1][0] = 3;

a[1][1] = 4;

//what is this ?! Are you kidding me ?!

//----------------------

printf("%d\n",0[*(a)]);

printf("%d\n",*(*(a)+1));

printf("%d\n",3[*(a)-1]);

printf("%d\n",1[*(a)+2]);

return 0;

}

呵呵,这段代码也挺让人抓狂的,没人会这么做,这么做的不是优秀的程序员。我还是那句话,夸张化来说明一些道理。不这么写,但是一定要明白为什么可以这么写,这是我的一点追求。

如果上面一维数组的讲解清楚了,那么二维数组其实不难理解。

先来看看定义:

int a[2][3];

代表什么意思?可以有很多理解,有些人觉得这可以看成是一个类似坐标的矩阵,比如把第一个[]里面的想成是x轴,第二个[]里面是y轴,所以这样对a[1][2]就很容易理解,这样理解是可以的。

有意思的是,它不过就是一维数组里面有个一维数组而已。拿a[2][3]举例,也就是说,首先,数组名是 a ,它是一个一维数组a[2],这个一维数组的每一个元素放着什么呢?放着3个元素,把表达式就写成a[2][3]。跟一维数组一样,数组名 a 是指针,默认指向a[0][i],但是问题来了,因为a[0][i]当中的内存块里面有三个int型的分别是a[0][0],a[0][1],a[1][2],究竟指向哪个呢?哪个都不指向,就只是指向a[0][i]而已,那么指向a[0][0]的指针在哪?在这:*a 。  *a 就是指向a[0][0]的指针,明白这种关系吗?这里有个双重指针。我结合一维数组来解释一下:

一维数组中,a 是指针指向首元素,那么有等式【1】 *a = a[0];

二维数组中,a 是指针指向首元素a[0][i],那么利用上面的等式【1】,a[0][i]可以推导写出这样的等式:a[0][i] = *a[i],*a 可以看成是数组名,所以,*a 就是指向 a[0][0] 的指针,这样就清楚多了,呼~

所以,理清楚这个关系,输出**a,也就是输出a[0][0]了,*(*a+1),当然就是a[0][1]。

所以,对于三维数组也清楚了吧,***a 就是 a[0][0][0],多维数组以此类推……

对于这样的表达式:0[*(a)],也能理解了,推导:(见笑,笔者对逻辑步骤比较感兴趣)

0[*(a)] = *(a)[0] = *a[0] = a[0][0];

恩,对c语言的数组与指针说得有点复杂,但这些确实很重要,平时编程可以不这么写,但是一定要懂得里面的原理,这样的好处不是让自己能运用,而是让自己不会运用错误。(指针操作错误可能引发很大的麻烦)

水平有限,有些包含不到,有些分析欠佳的,还请谅解。

阅读(692) | 评论(0) | 转发(0) |

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值