Basically, variables pointer
and pointer2
have different types, however they'll both behave similarly, with the exceptions:
– there will be no array to pointer decay occurring for pointer2
like it does for initial arr
, i.e.: e.g.:
#include <stdio.h>
int arr[5] = {1,2,3,4,5};
int *pointer = arr;
int (*pointer2)[5] = &arr;
void func(int *in_arr)
{
printf("1st: %i, 5th: %i\n", in_arr[0], in_arr[4]);
}
int main(void)
{
func(pointer);
func(pointer2); /* generates a warning (in GCC) */
func(arr); /* works with no issues*/
}
The warning will be:
ex.c: In function ‘main’:
ex.c:9:14: warning: passing argument 1 of ‘func’ from incompatible pointer type [-Wincompatible-pointer-types]
9 | func(pointer2);
| ^~~~~~~~
| |
| int (*)[5]
ex.c:4:24: note: expected ‘int *’ but argument is of type ‘int (*)[5]’
4 | void func(int *in_arr) {
| ~~~~~^~~~~~
– pointer arithmetic will behave differently, pointer+1
will point at second element, while pointer2+1
will point after the array pointer2
.
IMO, the (type*)[size]
pointers are quite peculiar thing in C. They'll allow, for example, to perform basically a cast to an array type, which is a quite strange thing to do in C – normally, you cannot cast anything to an array type (like.: func( (int [5]) ints_pointer )
, however with pointer-type to an array, it's possible to cast to it, so that, e.g.:
// same preamble as in previous example…
void func(int (*in_arr)[5]) {
printf("1st: %i, 5th: %i\n", ((int *)in_arr)[0],
((int *)in_arr)[4]);
}
int main(void) {
/* ·•Casts•· to a ·•pointer-to-array•· type to mute warnings */
func( (int(*)[5]) pointer );
func( (int(*)[5]) arr );
/* Generates no warning (in GCC) */
func(pointer2);
}
works with no issues.