In your particular example
int arr[10]
int (*ptr)[10];
ptr = & arr; //points to the base address of an array of 10 integers
for (i = 0; i < 10; i++) //prints the values
printf("%d\n", *(*ptr + i)); //NOTE: same as `ptr[0][i]`
there's no advantage or at least no advantage being utilized.
*(*ptr+i)
with int (*ptr)[10];
will/should generate the same assembly as
*(ptr+i)
would with int ptr[10];
(Note: some/many might find ptr[0][i]
and ptr[i]
respectively as more readable renderings of these expressions)
Example:
int get_nth(int (*X)[10], int N) { return *(*X+N); }
int get_nth_(int *X, int N) { return *(X+N); }
x86_64 output (gcc -O3 or clang -O3):
get_nth: # @get_nth
movsxd rax, esi
lea rax, [rdi + 4*rax]
ret
get_nth_: # @get_nth_
movsxd rax, esi
lea rax, [rdi + 4*rax]
ret
https://gcc.godbolt.org/z/up7HXc
If int (*ptr)[10]
were derived from a multidimensional array
as in
int multidim[5][10]; //array 10 or array 5 of int
int (*ptr)[10]=&multidim[1];
you could use the first index to jump the pointer in increments of 10*sizeof(int)
in addition to using the second one to jump in increments of sizeof(int)
(as with a plain int*
).
In a standalone example (i.e., where the 10-int block isn't part of a multidimensional array), probably the only "advantage" of int(*)[10]
is that it retains the sizeof
information (even across a function call boundary), and you could conceivably use this for explicit bounds-checking.
Bounds-checking example:
#include <stdio.h>
#define CHECKED_SUBSCRIPT(PtrArray, Index) (*(PtrArray))[BOUNDCHECK(Index,ARRCNT(*(PtrArray)))] /*{{{*/
#include <assert.h>
static inline size_t BOUNDCHECK(size_t Index, size_t Bound)
{
assert(Index < Bound);
return Index;
}
//sizeof(A) or void (=>error) if A isn't an array
#define ARRSZ(A) (+ sizeof(A) + 0* /*{{{*/\
_Generic((__typeof(&(A)[0])*)0, __typeof(__typeof(A)*):(void)0,default:0) ) /*}}}*/
#define ARRCNT(A) (ARRSZ(A)/sizeof((A)[0])) /*}}}*/
int main()
{
int arr[10]={0,2,4,6,8,10,12,14,16,18};
int (*ptr)[10] = &arr;
for (int i = 0; i < 20; i++){
printf("%d\n", CHECKED_SUBSCRIPT(ptr,i));
}
}
Output:
0
2
4
6
8
10
12
14
16
18
a.out: boundschecking.c:7: BOUNDCHECK: Assertion `Index < Bound' failed.