Reputation: 183978
In Find size of array without using sizeof, the size of an array is computed via
int arr[100];
printf ("%td", (&arr)[1] - arr);
Now, for the purposes of pointer arithmetic, arr
is considered the element of a single-element array, so
&arr + 1
is a pointer one-past the end of that (conceptual) single-element array, so when the address of arr[0]
is subtracted, the number of elements in arr
is obtained.
In (&arr)[1]
, that pointer is the operand of the indirection operator,
(&arr)[1] ≡ *(&arr + 1)
and the resulting array expression is then converted to an int*
as per 6.3.2.1 (3).
So far, so good. But the last sentence in 6.5.6 (8) (Additive operators),
If the result points one past the last element of the array object, it shall not be used as the operand of a unary
*
operator that is evaluated.
forbids the evaluation of the indirection operator there.
The question is whether the indirection operator is evaluated in
*(&arr + 1) - arr
(in which case that expression would invoke undefined behaviour) or the array-to-pointer conversion annihilates the evaluation (in which case all is well), like taking the address (&(*(&arr + 1))
) or applying sizeof
to it would..
Upvotes: 3
Views: 230
Reputation:
I think the standard is pretty clear that the *
operator is evaluated here. The result of the evaluation is an lvalue which is never converted to a value, but the result of the evaluation is used nonetheless.
There is a special exception when the address is immediately taken using the &
operator: in &*x
, where x
has type T *
, x
is evaluated, but the *
and &
operators are not. There is no intermediate lvalue of type T
at runtime of which the address is taken. So &*x
is valid even when x
is a null pointer or one past the end of an array.
Since you are not using the &
operator to take the address, that exception does not apply. There is no similar exception for the array-to-pointer conversion, so even when x
is an array type, *x
is invalid if x
does not actually point to any object.
Upvotes: 4
Reputation: 477570
You want to do this: For any T x;
, it is true that &x + 1
is the address just past the end of x
, and numerically it is a pointer that is obtained by incrementing &x
by sizeof(T)
(so the sizeof
is still there!).
Now if T = U[N]
, then x
is an array of N
elements of type U
. But the pointer to such an array is also a pointer to the first element of such an array. So we can reinterpret &x
(which is a (T*)[N]
) to a U*
, and we can do the same with &x + 1
. But now those pointers are of type U*
, so their difference counts the number of elemenets.
So the array size is:
(U*)(&x + 1) - (U*)(&x)
Note that because of array-to-pointer decay, (U*)(&x)
is actually the same pointer as the decay of x
.
Upvotes: 0