C 中下标与指针杂谈

https://zhuanlan.zhihu.com/p/399327901

很久以前就想写一些文章记录一下学习中碰到的种种,但一直忙于他事外加文思枯竭未曾发布文章,近日阅读  Pointers On C (C和指针) 略有所感,聊胜于无

任何比C语言更低级的语言,都不足以完整地抽象一个计算机系统; 任何比C高级的语言,都可以用C来实现。

下标的实现方式

C 中下标引用与其他的语言的下标引用很相似,不过它们的实现方式略有不同。C 的下标值总是从零开始,并且不会对下标值进行有效性检查。除了优先级不同,下标引用操作符和间接访问表达式是等价的。它们的映像关系如下:

array[下标]
*(array + (下标))

下标应用实际上是通过后面这种形式实现的。


数组中的下标引用

动图

int array[10];
int *ap = array + 2;

对指针进行下标引用

在这个例子中 ap[0] 的值为什么呢?

“不能这样做,ap 不是一个数组!” 如果你这样想就大错特错了,根据上文中提出的下标引用的实现方式中可以知道,这个表达式等价于 *(ap+(0)) 即 *(array + 2) 也就是 array[2]

对指针进行负的下标引用

接下来也有一个类似的例子。

ap[-1]

此时的你心中一定有个大大的问号:“为什么会是负的下标?其他语言里面...”

这就是将其他语言中的惯性思维带入到了 C 的学习中。ap 指向数组的第 3 个元素,所以使用偏移量 -1 可以得到它的其哪一个元素,也就是 array[1]。

奇奇怪怪的表达方式

2[array]

尽管你的心中肯定会有许多的疑惑,但是,它是合法的!

根据下标引用的实现方式,把它转换成对等的间接访问表达式,你就会发现其中的奥妙

*(2 + (array))

内括号其实是冗余的,而且加法操作符的两个操作时是可以交换位置的,所以它等价于:

*(array + 2)

也就是说: 2[array] 与 array[2] 是等价的。

这个方式是可行的,对编译器来说这两种形式没有什么差别,但是会严重影响程序的可读性。

指针与下标的效率问题

如果可以互换地使用指针表达式和下标表达式,应该选择哪一种方式?

假定这两种方式都是正确的,下标绝对不会比指针更有效率,但指针有时会比下标更有效率。

下标表达式:

int array[10], a;
for (a = 0; a < 10; a += 1;)
	array[a] = 0;

指针表达式:

int array[10], *ap;
for (ap = array; ap < array + 10; ap++)
	*ap = 0;

这两种实现方式就结果而言并无不同,但是问题来了,哪一种方式的效率更高?

指针表达式

在下标表达式中,为了对下标表达式求值,编译器在程序中插入指令,取得 a 的值,并把它与整型的长度(也就是 4)相乘。而对于指针表达式来说,只需要 1 这个值与整型的长度相乘,然后再与指针相加。这个乘法只需要在编译时进行一次。

所以使用指针表达式将会更加节省时间和空间。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值