Daniel Fischer
Daniel Fischer

Reputation: 183978

Does the array-to-pointer conversion annihilate the evaluation of the indirection operator?

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

Answers (2)

user743382
user743382

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

Kerrek SB
Kerrek SB

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

Related Questions