Pointers on C——8 Arrays.3

*ap + 6 Be careful, there are two operators here; which goes first? The indirection. The result of the indirection is then added to six, so this expression is the same as array[2] + 6.

小心!这里有两个操作符,哪一个先执行呢?是间接访问。间接访问的结果再与6相加,所以这个表达式相当于表达式array[2] + 6


*(ap + 6) The parentheses force the addition to go first, so this time we get the value of array[8]. Observe that the indirection used here is in exactly the same form as the indirection of a subscript.

括号迫使加法运算首先执行,所以我们这次得到的值是array[8] 。注意这里的间接访问操作和下标引用操作的形式是完全一样的。


ap[6] Convert this subscript to its indirection form, and youʹll see the same expression we just did, so it has the same answer.

把这个下标表达式转换为与其对应的间接访问表达式形式,你会发现它就是我们刚刚完成的那个表达式,所以它们的答案相同。


&ap This expression is perfectly legal, but there is no equivalent expression involving array because you cannot predict where the compiler will locate ap relative to array.

这个表达式是完全合法的,但此时并没有对等的涉及array 的表达式,因为你无法预测编译器会把ap 放在相对于array 的什么位置。


ap[-1] Howʹs that again, a negative subscript? A subscript is just an indirection expression; convert it to that form and then evaluate it ap points at the third element (the one whose subscript is two), so using an offset of ‐1 gets us the previous element: array[1].

怎么又是它?负值的下标!下标引用就是间接访问表达式,你只要把它转换为那种形式并对它进行求值。ap 指向第3 个元素(就是那个下标值为2 的元素),所以使用偏移量-1使我们得到它的前一个元素,也就是array[l] 。


ap[9] This one looks fine but is actually a problem. The equivalent expression is array[11], but the problem is that there are only ten elements in the array. Evaluating the subscript produces a pointer expression that runs off the end of the array, which makes this illegal according to the Standard. However, few compilers detect this error,so the program goes merrily on its way. But what does the expression do? The Standard says that its behavior is undefined, but on most machines it accesses whatever value happens to be stored in the second location beyond the end of the array. You can sometimes figure out what this value is by asking the compiler to produce an assembly language version of the program and examining that code, but there is no universal way to predict what value will be stored there. Thus, this expression will access (or, if used as an L‐value, will change) the value of some random variable. This result is not likely to be what you wanted.

这个表达式看上去很正常,但实际上却存在问题。它对等的表达式是array[ 11] ,但问题是这个数组只有10 个元素。这个下标表达式的结果是一个指针表达式,但它所指向的位置越过了数组的右边界。根据标准,这个表达式是非法的。但是,很少有编译器能够检测到这类错误,所以程序能够顺利地继续运行。但这个表达式到底干了些什么?标准表示它的行为是未定义的,但在绝大多数机器上,它将访问那个碰巧存储于数组最后一个元素后面第2 个位置的值。你有时可以通过请求编译器产生程序的汇编语言版本并对它进行检查,从而推断出这个值是什么,但你并没有统一的办法预测存储在这个地方的到底是哪个值。因此,这个表达式将访问(或者,如果作为左值,将修改)某个任意变量的值。这个结果估计不是你所希望的。


The last two examples show why subscript checking is a difficult task in C. The Standard does not require that it be done at all; the earliest C compilers didnʹt check subscripts, and most current ones still donʹt. The fact that subscripts can be applied to arbitrary pointers, not just array names, makes the job difficult. The validity of a subscript applied to a pointer variable depends on where it happens to be pointing at the time, as well as the value of the subscript.

最后两个例子显示了为什么下标检查在C 中是一项困难的任务。标准并未提出这项要求。最早的C 编译器并不检查下标,而最新的编译器依然不对它进行检查。这项任务之所以很困难,是因为下标引用可以作用于任意的指针,而不仅仅是数组名。作用于指针的下标引用的有效性既依赖于该指针当时恰好指向什么内容,也依赖于下标的值。


Consequently, subscript checking in C involves more overhead than you might first think. Instructions must be inserted into the program to verify that the result of the subscript refers to an element in the same array as the pointer. This comparison requires information about the locations and sizes of all arrays in the program, which will take some space. The information must also be updated as the program runs to reflect automatic and dynamically allocated arrays, which will take some time. Thus,compilers that offer subscript checking usually also offer a way to turn it off.

结果, C 的下标检查所涉及的开销比你刚开始想象的要多。编译器必须在程序中插入指令,证实下标表达式的结果所引用的元素和指针表达式所指向的元素属于同一个数组。这个比较操作需要程序中所有数组的位置和长度方面的信息,这将占用一些空间。当程序运行时,这些信息必须进行更新,以反映自动和动态分配的数组,这又将占用一定的时间。因此,即使是那些提供了下标检查的编译器通常也会提供一个开关,允许你去掉下标检查。


Hereʹs an interesting, though admittedly arcane, tangent. In the context of the previous declarations, what is the meaning of this expression?

这里有一个有趣的,但同时也有些神秘和离题的例子。假定下面表达式所处的土下文环境和前面的相同,它的意思是什么呢?


2 [array]


The answer may surprise you: it is legal. Convert it to the equivalent indirection expression and you will see its validity:

它的答案可能会令你大吃一惊:它是合法的。把它转换成对等的间接访问表达式,你就会发现它的有效性:


* ( 2 + ( array ) )


The inner parentheses are redundant, so we can delete them. Also, addition is commutative, so this expression has exactly the same meaning as

内层的那个括号是冗余的,我们可以把它去掉。同时,加法运算的两个操作数是可以交换位置的,所以这个表达式和下面这个表达式是完全一样的


*( array + 2 )


meaning that the original, funny‐looking expression is identical to array[2].

也就是说,最初那个看上去颇为古怪的表达式与array[2] 是相等的。


This quirk exists because of the way that subscripts are implemented in C.Either form is fine as far as the compiler is concerned. However, you should never write 2[array]: it only makes the program harder for others to read.

这个诡异技巧之所以可行,缘于C 实现下标的方法。对编译器来说,这两种形式并无差别。但是,你绝不应该编写2[array] ,因为它会大大影响程序的可读性。


上一章 Pointers on C——8 Arrays.2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值