数组与指针

        前两天读了《C陷阱与缺陷》和《C专家编程》 两本书。回过头来看,在读这两本书之前我对C的认识实在是处于似懂非懂之间,尽管也写过不少代码。《C陷阱和缺陷》是作者收集的C语言中常见的认识和应用错误。其中讲到程序兼容性有一章,尤为难得,因为一般书籍很少涉及该话题。至于《C专家编程》,我强烈推荐。一方面是因为作者对C的理解很深刻,另一方面则是由于作者的文字流畅自如,其中还引用了不少关于C的趣闻,读着感觉很好,一点都不枯燥无味。《C专家编程》对数组和指针的分析尤为深刻。至少我觉得读过之后应该不会再把两者混淆起来了。

        指针是C的精髓。数组和指针的关系包括以下几点:

       1. 声明和定义中的数组和指针不等价。两本书中都给出了如下的例子:

//  File 1
int  array[ 10 =  { 0 };

//  File 2
extern   int   *  array;

         这里的 array 指针和 array 数组绝不是一个东西。这样写法会引起错误(如果别的地方没有给出array指针的定义)。

        2. 在使用时,数组和指针被编译器转换为同样的代码(当然不能把数组名当作左值进行++等操作)。也就是说,a[b] 与 *(a + b) 是等价的。也因此,下面的代码是合法的(很怪异但是却有效,可以去骗菜鸟了):

int  array[ 10 ];
array[
0 =   0 ;     // 数组的第一个元素置为0
1 [array]  =   1 ;     // 数组的第二个元素置为1

int   *  ptr  =  array;
((
int   * )(( int )ptr + sizeof (array)))[ - 1 =   9 ;      // 数组的最后一个元素置为9

        也正是这样,作为实参的数组名其实是将数组的地址传递给了调用它的函数,即数组作为实参是传址调用。在一个函数中对实际是一个数组的参数进行 sizeof 求值,并不能求出这个数组的长度,即使形参声明为数组也不行(实际将返回指针的长度)。

        3. 当然,在内部实现上数组和指针还是不同的。这个可以把数组名看做定值,因此访问数组某个变量只需要将首地址加上偏移量。而指针指向的区域的首地址必须先访问指针所在的地址才能获得,然后将这个地址中的内容(即其指向内存区域的首地址)加上偏移量才能求出某个元素的真实地址。

        4. 涉及二维数组的情况更为复杂。《C专家编程》指出C并不存在二维数组,而只存在数组的数组。即某数组的每个元素都是一个数组。因此一个二级指针(指针的指针)是不能直接指向一个二维数组的(这个错我经常犯……),必须写成:

int  a[ 2 ][ 3 ];
int   *  p1  =   & a[ 0 ][ 0 ];        // 合法,指向二维数组第一行的第一个元素
int  ( *  p2)[ 3 =   & a[ 0 ];     // 合法,指向二维数组的第一行。这里[3]中的3不能省略
int   **  p3  =  a;                 // 错误!二级指针不能指向二维数组!

        差不多最重要的几点就是这样。诸位见笑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值