In int arr[...]
arr is (represents) the address of the 1st element of arr.
In int *p
p contains an address to an int (actually, similarly to arr, p is (represents) the address where an address to an int is, but that's maybe confusing).
When indexing arr, arr[i]
and p[i]
, the compiler performs a similar calculation
arr[i]
=> *(arr + i*sizeof(int))
p[i]
=> *((p) + i*sizeof(int))
if there is a slight difference here, is that the compiler uses directly the address of arr, while it takes the value of p (there is an indirection). If p = arr
arr -> int0 int1 int2 ...
p -> (address of arr) -> int0 int1 int2
but practically that indirection does not affect how the code is written.
Answering @CrisLuengo:
“if there is a slight difference here, is that the compiler uses directly the address of arr, while it takes the value of p (there is an indirection).” I don’t understand what you are saying here. The two are identical and produce identical code.
Actually no ; these pieces of code
int arr[5]; int *p;
int x = arr[1]; int x = p[1];
the int x = ...
produces the following assembly
# arr.c:6: int x = arr[1]; # p.c:6: int x = p[1];
movl -28(%rbp), %eax # arr[1], tmp84 movq -8(%rbp), %rax # p, tmp84
movl %eax, -36(%rbp) # tmp84, x movl 4(%rax), %eax # MEM[(int *)p_2(D) + 4B], tmp85
movl %eax, -12(%rbp) # tmp85, x
Please note that in this particular example, if the code is compiled with optimizations, the compiler may be able to skip the step of reading the value of p
and directly use the address of arr
, resulting in similar assembly code for accessing arr[1]
and p[1]
. However, in general, accessing an array element is typically faster than accessing an element through a pointer due to the additional step of retrieving the pointer's value.
A difference, is that arr being an address, is fixed (arr++
and arr = arr2
are illegal). But p contains a value (an address) that can be changed, incremented etc.
And interesting aspect of the similarity is when passing arr to a function
void f(int a[]) { ... }
f(arr);
The function f takes a parameter which is variable. f can take arr, arr2, ... Thus a
in f is treated like a pointer to an int
void f(int a[]) { int y = *a++ ; int x ; a = &x; ... }
Int your case of mxArray *plhs[]
and mxArray **plhs
this is the same logic. But, instead of int
mxArray *plhs[]
is an array of pointers to mxArray
mxArray **plhs
is a pointer to a pointer to a mxArray