3

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 explicit sizeof.

Anyone have any idea how it was done?

Thanks a bunch!

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Raul Grigorașcu
  • 71
  • 1
  • 1
  • 5
  • 2
    maybe something like `*(&a + 1) - 1` (not checked/tested and I doubt this is well-defined) –  Jul 12 '17 at 14:00
  • 1
    See my question: [Is `*((*(&array + 1)) - 1)` safe to use to get the last element of an automatic array?](https://stackoverflow.com/questions/32537471/is-array-1-1-safe-to-use-to-get-the-last-element-of-an-automatic). In short, `*(&array + 1)` invokes UB. – Spikatrix Jul 12 '17 at 14:01
  • 2
    Not clear what you mean. There is no "trick" involved. ("Tricks" are most times a bad idea anyway.) – too honest for this site Jul 12 '17 at 14:02
  • 1
    @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 .... –  Jul 12 '17 at 14:02
  • 1
    `((int *)(&a + 1))[-1]` would be well-defined though (avoids the problem of dereferencing the past-the-end pointer) – M.M Jul 12 '17 at 14:05
  • 2
    @M.M is `(int *)(&a + 1)` cast valid? The pointer types are incompatible, I think... – Eugene Sh. Jul 12 '17 at 14:07
  • 3
    Is there a good reason to avoid `sizeof()`? Or is it a pure academical question? – Ctx Jul 12 '17 at 14:10
  • 1
    Is `a[sizeof a / sizeof *a - 1]` not concise enough? – Ian Abbott Jul 12 '17 at 14:11
  • 1
    @EugeneSh. the whole purpose of a pointer cast is to cast between incompatible types – M.M Jul 12 '17 at 14:11
  • @M.M But then there is a pointer arithmetic performed on it. Technically it is within the boundaries of `a`, but `a` has a different type of the one pointed by the pointer the arithmetic is performed on. So it looks a bit suspicious to me. – Eugene Sh. Jul 12 '17 at 14:21
  • @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. – chux - Reinstate Monica Jul 12 '17 at 14:22
  • Wow, thanks guys! I knew it was something remarkably simple. Thanks alot! – Raul Grigorașcu Jul 12 '17 at 14:24
  • @chux `a + sizeof a / sizeof *a - 1` is a pointer – JeremyP Jul 12 '17 at 14:32

2 Answers2

10

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
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 2
    Note: 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. – chux - Reinstate Monica Jul 12 '17 at 14:28
5

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.

M.M
  • 138,810
  • 21
  • 208
  • 365