C pointer to last element of array
Solution 1
I can suggest the following solution
#include <stdio.h>
int main( void )
{
int a[4] = { 0, 1, 2, 3, };
int *p = (int *)(&a + 1) - 1;
printf("*p = %d\n", *p);
return 0;
}
The program output is
*p = 3
Solution 2
You're probably thinking of something that involved &a + 1
, which is a pointer to the memory just past the end of the struct.
However, (&a)[1][-1]
, or the identical expression but substituting pointer notation for array notation, *(&a + 1))[-1]
or *(*(&a + 1) - 1)
, is technically undefined behaviour. But someone might have written this as a "clever trick" not realizing it was undefined.
((int *)(&a + 1))[-1]
is well-defined and does the job, although arguably harder to read than just writing straightforward code.
Raul Grigorașcu
Updated on June 04, 2022Comments
-
Raul Grigorașcu almost 2 years
Lets say we have an array
int a[4];
there was a neat trick using pointer arithmetics to find the last element. As far as i can recall it was using the address of 'a' and incrementing it so that it will go point immediately after the array and then going one position back. The thought behind the incrementing was that that there was an implicit
sizeof
being done. There was nowhere any explicitsizeof
.Anyone have any idea how it was done?
Thanks a bunch!
-
Admin almost 7 yearsmaybe something like
*(&a + 1) - 1
(not checked/tested and I doubt this is well-defined) -
Spikatrix almost 7 yearsSee my question: Is
*((*(&array + 1)) - 1)
safe to use to get the last element of an automatic array?. In short,*(&array + 1)
invokes UB. -
too honest for this site almost 7 yearsNot clear what you mean. There is no "trick" involved. ("Tricks" are most times a bad idea anyway.)
-
Admin almost 7 years@kay I doubt it because although it's ok to have a pointer pointing one after the end of an object, for my "trick" here, I need to dereference this pointer ....
-
M.M almost 7 years
((int *)(&a + 1))[-1]
would be well-defined though (avoids the problem of dereferencing the past-the-end pointer) -
Eugene Sh. almost 7 years@M.M is
(int *)(&a + 1)
cast valid? The pointer types are incompatible, I think... -
Ctx almost 7 yearsIs there a good reason to avoid
sizeof()
? Or is it a pure academical question? -
Ian Abbott almost 7 yearsIs
a[sizeof a / sizeof *a - 1]
not concise enough? -
M.M almost 7 years@EugeneSh. the whole purpose of a pointer cast is to cast between incompatible types
-
Eugene Sh. almost 7 years@M.M But then there is a pointer arithmetic performed on it. Technically it is within the boundaries of
a
, buta
has a different type of the one pointed by the pointer the arithmetic is performed on. So it looks a bit suspicious to me. -
chux - Reinstate Monica almost 7 years@IanAbbott detail
a[sizeof a / sizeof *a - 1]
is the last element of the array. OP wants "pointer to last element of array". Presumable&a[sizeof a / sizeof *a - 1]
would work. -
Raul Grigorașcu almost 7 yearsWow, thanks guys! I knew it was something remarkably simple. Thanks alot!
-
JeremyP almost 7 years@chux
a + sizeof a / sizeof *a - 1
is a pointer
-
-
chux - Reinstate Monica almost 7 yearsNote: the
int*
cast appears ok per "A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined." C11 §6.3.2.3 7.