数组的某个成员可以用数组的基地址加上一个偏移量来表示 。我们可以声明一个指针double *p;,把它作为基地址,然后就可以像数组一样在这个基地址上使用偏移量 。在基地址上,我们可以找到第1个成员p[0]的内容,在基地址上前进一步可以找到第2个成员p[1]的内容,接下来以此类推 。因此,只要提供一个指针以及两个相邻成员之间的距离,就可以把它作为数组使用了 。
我们可以直接采用基地址加偏移量的书面形式,类似(p+1) 。正如教科书所描述的那样,p[1]等同于 *(p+1),这就解释了为什么数组的第1个成员是p[0] == *(p+0) 。
这个理论提示了一些规则,用于在实际应用中表述数组和它们的成员 。
- 可以通过显式的指针形式double *p,或静态/自动形式double p[100]来声明数组 。
- 不管是哪种情况,第n + 1个数组成员都是p[n] 。不要忘了第一项是0而不是1,这样就可以采用特殊形式p[0] == *p 。
- 如果需要第n个成员的地址(而不是实际值),使用&符号:&p[n] 。当然,第1个成员的地址就是&p[0] == p 。
例1 一些简单的指针运算(arithmetic.c)
文章插图
? 使用特殊形式*evens写入到evens[0] 。
? 成员1的地址,赋值给一个新指针 。
? 引用数组第1个成员的通常方式 。
下面我再送你一个很好的技巧,这个技巧建立在指针运算规则“p+1表示数组中下一个成员的地址(&p[1])”的基础上 。根据这个规则,我们不需要在遍历数组的循环中使用下标 。在例2中我们就使用了一个备用指针来指向list的头部,然后用p++在数组中向前遍历,直到数组尾部的NULL标记,从而获得了整个数组值 。如果你查看了接下来的指针声明的提示,会更容易理解这种用法 。
例2我们可以利用p++表示“前进到下一个指针”实现循环的流水化
文章插图
自己动手
如果不了解p++,你打算怎样实现这个目标?如果目标是为了实现简洁的语法表示形式,基地址加偏移量这个技巧并不能提供太多的帮助,但它确实解释了C的许多工作原理 。事实上,我们可以考虑一下使用结构,例如:
文章插图
作为一种智力模型来分析,我们可以把list看成是基地址,list[0].b与基地址的距离正好用来表示b 。也就是说,假设list的位置是整数(size_t)&list,b位于(size_t)&list + sizeof(int);,这样list[2].d的位置将是(size_t)&list + 6*sizeof(int) + 5*sizeof(double) 。根据这种思路,结构就与数组非常相似了,区别是结构的成员是用名称而不是序号表示的,并且它们具有不同的类型和长度 。
这个思路并不是非常正确,因为存在对齐这个因素,系统可能会决定数据需要位于某个特定长度的内存块中,因此字段尾部可能会填充一些额外的空间,使下一个字符从正确的位置开始,并且结构的尾部可能也会进行填充,使结构列表中的每个结构能够大致对齐[C99和C11,§6.7.2.1(15)和(17)] 。stddef.h头文件定义了offsetof宏,它精确地描述了基地址加领偏移量的思路:list[2].d的实际地址是(size_t)&list + 2*sizeof(abcd_s) + offsetof(abcd_s, d) 。
顺便说一下,在结构的起始处不可能出现填充,因此list[2].a肯定等于(size_t)&list+ 2*sizeof(abcd_s) 。
下面是个笨拙的函数,它以递归的方式对列表中的成员进行计数,直到遇到值为0的成员 。假设我们想把这个函数用于零值为合理数据的任何类型的列表,因此我们让它接受一个void指针(当然这不是一种好的思路) 。
文章插图
基地址加偏移量的规则解释了为什么这种做法是不行的 。为了表示a_list[1],编译器需要知道a_list[0]的准确长度,这样才能知道应该从基地址偏移多少 。但是,由于没有与之相关联的类型,它无法计算这个长度 。
typedef作为一种教学工具任何时候当我们遇到一种复杂的类型时,类似于指向某种类型的指针的指针的指针等情况,可以考虑用typedef进行简化 。
例如,下面这个常见的定义:
文章插图
有效地减少了字符串数组的视觉混乱,使它们的意图变得清晰 。
推荐阅读
- 远离刀山火海 12种不吉利厨房风水让你破财短命
- 8种风水格局让你抑郁 悲痛欲绝精神崩溃
- 婚房“禁忌” 80后新人新婚不得不知道六大事
- 职工社保转农村社保怎么办理?
- 面条加入什么调料最好吃?
- 转让店铺合同怎么写合法 店铺转让需要签什么合同
- 这些“养生”茶,很多时候你都喝错了
- 红茶啤酒保护心脏 教你DIY花式啤酒
- 柚子润燥美白又祛斑 简单6步教你自制蜂蜜柚子茶
- 饵料|小杂鱼闹窝不胜其烦,矫枉过正得不偿失,教你一个正确的应对方法