2.3 数据集合与指针的算术运算

2.3 数据集合与指针的算术运算

指针在C语言中最常见的用途就是用来引用数据集合。数据集合是由多种相关联的基础数据构成的数据体。C语言支持两种数据集合:结构和数组。(虽然联合与结构类似,但一般它单独被归为一类)

2.3.1 结构

结构通常是由各种各样的有序的基础数据组成的,从而它可以被看作一个单一而连续的数据类型。结构指针是构建一个数据结构的重要组成部分。结构使我们能把数据捆绑在一起,指针使我们能够让这些捆绑包在内存中一个一个连接起来。用这些连接起来的结构,我们可以加以组织并用来解决实际的问题。

这里有一个例子,我们考虑把内存中一些元素组合起来形成一个链表(见第5章)。要做到这一点,我们可能会使用下面代码所示的像listElmt一样的结构,我们用每个元素的next来指向下一个元素,并把最后一个元素的next设定为NULL来表示链表的结尾。同时,每个元素的data指向此元素所包含的数据。一旦生成了这样一个列表,我们就可以用next指针遍历整个链表。

typedef struct ListElmt_ {
    void               *data;
    struct ListElmt_   *next;
} ListElmt;

结构ListElmt也指出了关于结构指针的另一个重要方面:结构不允许包含自身的实例,但可以包含指向自身实例的指针。这种编程思想非常重要,因为很多数据结构都可能是由它自身的结构变量所组成,例如,在一个链表中,每个ListElmt结构都指向另一个ListElmt结构。有些数据结构甚至会包含多个由自身结构类型组成的结构,例如在一个二叉树中(见第9章),每个结点同时指向其它两个树的结点。

2.3.2 数组

数组是在内存中连续排列的同类元素的序列。在C语言中,数组与指针密不可分。事实上,当一个数组在表达式中出现时,数组会被转换为一个指向数组第一个元素的固定指针。考虑到这一点,以下两个函数是等价的。

Array Reference

Pointer Reference

int f()

    int a[10], *iptr;

    iptr = a;

    iptr[0] = 5;

 

    return 0; 

}

int g()

    int a[10], *iptr;

    iptr = a;

    *iptr = 5;

 

    return 0; 

}


为了理解指针与数组的关系,我做如下解释。我们知道要访问一个数组的第 i个元素,我们用表达式:

a[i]


之所以此表达式能够访问第i个元素,是因为在C语言中,这个表达式与指向a的第一元素的指针表达意思相同,也就是说等同于表达式:

*(a + i)

 

此表达式实际上是使用指针运算的规则来访问元素的。简单来说,当我们对指针进行加i操作时,我们实际得到了一个地址,这个地址由a所在的地址加上数据类型a所含字符大小乘以i得到;而并不是简单的在a所在的地址上加i个字节。当我们在指针上减去一个i时也是执行类似的操作。这样我们也就解释了为什么数组是从0开始的,因为数组的第一个元素在位置0。

例如:如果一个指针或数组包含5个4字节的整型数,并且起始地址为0x10000000,那么a[3]访问的地址为0x1000000c。这个地址是由0x10000000加上(3)(4)=12=0xc得到的(见图2.3a)。另一方面,当数组或指针包含的是20个字符型变量时,a[3]将访问地址为0x10000003。这个地址是由0x10000000加上(3)(1)=3=0x3得到的(见图2.3b)。当然,通过数组或指针引用一块数据与引用多块数据并没有什么不同,因此,很重要的一点是必须对数组或指针所引用的数据空间大小保持警惕,决不能越雷池一步。

把一个多维数组转换为指针与把一维数组转换为指针的过程类似。但是同时要知道在C语言中,多维数组其实是以行主序的方式存储的,这也就说明多维数组右边下标变化速度要比由左边下标变化来得更快。要访问一个二维数组第i行第j列的元素,我们用以下表达式:

a[i][j]


C语言在表达式中将a当做是指向该数组第一行的指针。整个表达式等价于:

*(*(a + i) + j)


图2.3 用指针运算来表示整型或字符型数组的方向方式

 

PS:

1、此书(Mastering Algorithms with C)译稿版权归本人(Love_Lei)及好友(bigship)共同所有,未经本人同意谢绝一切转载,并不得抄袭,模仿,盗版!更请大家监督盗版之人!

2、由于本人水平有限,如对译文有任何建议和异议,欢迎大家留言指正,我们共同讨论学习!谢谢!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值