c
int square(int n) { int a[n]; return (&a)[n] - a; }
解析
- 目的: 为了避免使用乘法运算.
- 要求: c99+
a
是一个指针, &a
即为该指针指向的地址. 所以 a[n]
的本质是一个指针指向一个数组. 而 (&a)[n]
的本质是那个指向一个数组的指针的地址.
而直接将指针进行运算时, 实际上是其地址在运算.
故而:
(&a)[n] - a == (&a)[n] - (&a)[0];
也就是说其返回的是地址 (&a)[n]
与 (&a)[0]
之间的元素个数. 每指向一个数组, 意味着指向着 n 个元素, 那个从地址 0 到地址 n 之间有着 n 个这样的指针, 即指向着 n*n 个元素.
所以本质上返回的其实是 n*n.
评价
某些时候,我们为了效率而 hack , 但多数时候这样的行为都是 UB(undefined behavior). 这个函数也是一样。
C11: 6.5.6 Additive operators (p9):
When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. The size of the result is implementation-defined, and its type (a signed integer type) is
ptrdiff_t
defined in the<stddef.h>
header. If the result is not re-presentable in an object of that type, the behavior is undefined.
(&a)[n]
显然既没指向同一个数组对象的元素,也没指向数组对象的末尾。所以,在 C11 标准中,这属于未定义行为。
另外,标准里还提到了,这里的返回值应该用 ptrdiff_t
较为合适。
Reference
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。