int p(int n)
{
int a[n];
//works on C99 and above
return (&a)[n] - a;
}
It returns n^2. Question is, how does it do that? After a little testing, I have found that between(&a)[k]
and (&a)[k+1]
is sizeof(a)
/sizeof(int)
. Why is that?
Obviously a hack... but a way of squaring a number without using the *
operator.
(&a)[n]
is equivalent to a pointer to int
at location
(a + sizeof(a[n])*n)
and thus the entire expression is
(&a)[n] -a
= (a + sizeof(a[n])*n -a) /sizeof(int)
= sizeof(a[n])*n / sizeof(int)
= sizeof(int) * n * n / sizeof(int)
= n * n
To understand this hack, first you need to understand the pointer difference, i.e, what happens when two pointers pointing to elements ofsame array are subtracted?
When one pointer is subtracted from another, the result is the distance (measured in array elements) between the pointers. So, ifp
points to a[i]
and q
points to a[j]
, thenp - q
is equal to i - j
.
Now I am expecting that you are aware of array name conversion to pointer, a
converts to pointer to first element of array a
. &a
is address of the entire memory block, i.e it is an address of arraya
. The figure below will help you to understand (readthis answer for detailed explanation):
This will help you to understand that why a
and &a
has the same address and how(&a)[i]
is the address of ith array (of same size as that ofa
).
So, the statement
return (&a)[n] - a;
is equivalent to
return (&a)[n] - (&a)[0];
and this difference will give the number of elements between the pointers (&a)[n]
and (&a)[0]
, which are n
arrays each of n
int
elements. Therefore, total array elements are n*n
=n
2.
NOTE:
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 representable in an object of that type, the behavior is undefined.
Since (&a)[n]
neither points to elements of the same array object nor one past the last element of the array object,(&a)[n] - a
will invoke undefined behavior.
Also note that, better to change the return type of function p
toptrdiff_t
.