From my understanding of C, you could treat a pointer variable and an array variable as equivalent, since they are both pointers ultimately (one to the local function stack, the other to any random point in memory).
I normally pass a pointer to a pointer (e.g. char ** pvar) when I need to return a pointer, so I can see how it makes little sense to pass it back to a dereferenced local array, since you can't change the position of a variable.
My expectation would be that if I try this, the compiler would let me do it, and then segfault or crash when I try to set the returning pointer value.
However, when trying to dereference an array type (&array), the compiler helpfully generates a warning about using incompatible types, then it passes the pointer to the array, essentially losing one level of indirection from the receiving function's point of view.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
void ptrptr(uint32_t** dptr)
{
printf("%x, %x\n", dptr, *dptr);
}
void oneptr(uint32_t* ptr)
{
printf("%08x, %x\t", ptr, *ptr);
ptrptr(&ptr);
}
int main()
{
uint32_t array[] = {1};
uint32_t *ptr = calloc(1, sizeof( uint32_t));
ptr[0] = 3;
oneptr(ptr); /* OK, passes an (uint32_t *) */
oneptr(array); /* OK, passes an (uint32_t *) */
ptrptr(&ptr); /* OK, passes an (uint32_t **) */
ptrptr(&array); /* ??, passes an (uint32_t *) */
return 0;
}
Compiling it gives me the warning
cc test.c -o test
test.c: In function ‘main’:
test.c:24:9: warning: passing argument 1 of ‘ptrptr’ from incompatible pointer type [-Wincompatible-pointer-types]
ptrptr(&array);
^
test.c:5:6: note: expected ‘uint32_t ** {aka unsigned int **}’ but argument is of type ‘uint32_t (*)[1] {aka unsigned int (*)[1]}’
void ptrptr(uint32_t** dptr)
^~~~~~
0061a008, 3 7ebfa144, 61a008
7ebfa154, 1 7ebfa144, 7ebfa154
7ebfa150, 61a008
7ebfa154, 1
I get the same result when I use gcc, clang and cl to compile it, so I'm fairly confident that this is not a compiler bug. The question then is, why is C silently passing a pointer ( uint32_t*) instead of a pointer to a pointer (uint32_t**) when I try to dereference an array?
&arrayis a pointer to an array, not a pointer to a pointer. Another one is that, in general,sizeof(ptr) != sizeof(array).ptrptrin the last case is not, as you seem to believe, auint32_t*, but auint32_t (*)[1]- a pointer to an array ofuint32_t, of length 1. It's also not clear what you mean by "silently" - you are getting a warning, aren't you?sizeofoperator, the_Alignofoperator, or the unary&operator, or is a string literal used to initialize an array. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)