要了解这种技巧,首先需要了解指针的区别,即,减去两个指向同一数组元素的指针时会发生什么?
当一个指针与另一个指针相减时,结果就是指针之间的距离(以数组元素为单位)。因此,如果p
指向a[i]
并q
指向a[j]
,则p - q
等于i - j
。
C11:6.5.6加法运算符(p9):
当减去两个指针时,两个指针都将指向同一数组对象的元素,或者指向数组对象的最后一个元素;结果是两个数组元素的下标不同。[...]。
换句话说,如果表达式P
和Q
分别指向数组对象的i
-th和j
-th元素,则表达式(P)-(Q)
具有值,i−j
只要该值适合于type对象ptrdiff_t
。
现在,我希望您知道将数组名转换为指针,a
并将其转换为指向array的第一个元素的指针a
。&a
是整个内存块的地址,即它是array的地址a
。下图将帮助您理解(请阅读此答案以获取详细说明):
这将帮助您理解第 i 个数组的原因a
和&a
地址,以及第(&a)[i]
i 个数组(与的大小相同)的地址如何a
。
所以,声明
return (&a)[n] - a;
相当于
return (&a)[n] - (&a)[0];
而这种差异将给出指针(&a)[n]
和之间的元素数量(&a)[0]
,它们是n
每个n
int
元素的数组。因此,总数组元素为n*n
= n
2。
注意:
C11:6.5.6加法运算符(p9):
当减去两个指针时,两个指针均应指向同一数组对象的元素,或者指向数组对象的最后一个元素;结果是两个数组元素的下标不同。结果的大小是实现定义的,并且其类型(有符号整数类型)ptrdiff_t
在<stddef.h>
标头中定义。如果结果无法在该类型的对象中表示,则该行为未定义。
由于(&a)[n]
既不指向同一数组对象的元素,也不指向数组对象的最后一个元素,因此(&a)[n] - a
都不会调用未定义的行为。
另请注意,最好将函数的返回类型更改p
为ptrdiff_t
。