Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forcing a decay of the array (for the lack of better title)

Inspired by this question: How does *(&arr + 1) - arr give the length in elements of array arr?

The following code will calculate the length of an array, albeit invoking undefined behavior:

int  arr[] = {5, 8, 1, 3, 6};
size_t len = *(&arr + 1) - &arr[0]; // len is 5

I believe, that by dereferencing the (&arr + 1) we are triggering undefined behavior. However, the only reason we are doing this is to immediately decay the result into int*, pointing to one element after the last one in original array. Since we do not dereference this pointer, we are well in defined zone.

The question thus is following: is there a way to decay into int* without dereferencing the undereferencable pointer and staying defined?

P.S. Mandatory disclaimer: yes, I can calculate the size of an array with sizeof operator and division. This is not the point of the question.

EDIT: I am now less sure that the indirection itself is undefined. I have found http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232 and from it looks it seems like there was an attempt to legalize the indirection per se, but I was not able to find any wording to this effect in actual standard.

like image 508
SergeyA Avatar asked Nov 07 '22 08:11

SergeyA


1 Answers

What is known as "decay" is "array-to-pointer conversion" in standardese, and it is clear that what you ask is impossible:

[conv.array]

An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”

There can be no lvalue referring to a non-existent array, and a rvalue (not converted from the lvalue) can't refer to the same array.


Now to clarify a few points:

  • &arr + 1 is a pointer pass the end of an object, and indirection is defined only on pointers to actual objects. The active issue is about null pointers, which isn't relevant to pointers pass the end of an object.
  • Pointer arithmetic is only defined on objects within the same array, even if you had int arr[2][5];, *(&arr + 1) decayed as int* is not considered part of the array arr[0], and so &arr[1][0] - &arr[0][0] is still undefined.
like image 89
Passer By Avatar answered Nov 15 '22 06:11

Passer By