You declared an array of 6 integers
int a[] = {1, 2, 3, 4, 5, 6};
That is the array has the type int[6].
The expression &a has the pointer type int ( * )[6]. And the expression &a+1 points to the memory after the array. So dereferencing the array like *(&a+1) you will get an expression of the array type int[6] that in turn is implicitly converted to a pointer of the type int *,
And in this call of printf
printf("%d \n",*(&a+1));
you are trying to output the pointer using the conversion specifier %d that invokes undefined behavior.
Instead you could write
printf("%p \n",( void * )*(&a+1));
and the value of the pointer expression (that points to the memory after the array) will be outputted.
In this call of printf
printf("%d \n",**(&a+1));
you are dereferencing the expression *(&a+1) explained above. As the value of the obtained pointer expression points beyond the array then dereferencing it invokes undefined behavior.
Instead of these two calls you could write for example using the expression &a
printf("%p \n",( void * )*(&a));
to output the address of the first element of the array and'
printf("%d \n",**(&a));
to output the value of the first element of the array.
Though it would be simpler to write
printf("%p \n",( void * )a );
and
printf("%d \n",*a );
And you will get the same result.
Or to output for example the address and the value of the second element of the array you could write
printf("%p \n",( void * )( a + 1 ));
and
printf("%d \n",*(a + 1 ) );
The last call of printf is equivalent to
printf("%d \n",a[1] ) );
Pay attention to that array designators used in expressions with rare exceptions are converted to pointers to their first elements.
**(&a + 1)? Using more sensible notation like*a[1].atoprintfvs&a? Can you explain this?