Consider the following code:
#include <stdio.h>
int ret_five() {
return 5;
}
int main() {
int x[5] = {1,2,3,4,5};
int (*p)();
p = &ret_five;
printf("%d\n", p()); // 1
p = ret_five;
printf("%d\n", p()); // 2
printf("%d\n", sizeof ret_five); // 3
printf("%d\n", sizeof &ret_five); // 4
printf("%d\n", (*p)()); // 5
printf("%d\n", (****p)()); // 6
printf("%p\n", p); // 7 // edited: replaced %d with %p
printf("%p\n", *p); // 8 // same here and in (8), (10)
printf("%p\n", **p); // 9
printf("%p\n", *******p); // 10
printf("%p\n", x); // 11
printf("%p\n", &x); // 12
return 0;
}
My questions are:
Lines (1) and (2) print the same result. Do
ret_five
and&ret_five
have the same data type? It seems like no, because lines (3) and (4) print different results.From a syntactical point of view, it seems to me that line (5) should be the right way to call the function that
p
points to, but of course lines (1) and (2) print 5 just fine. Is there a technical reason for this, or was it a design decision made because the calls in (1) and (2) look cleaner? Or something else?Line (5) makes perfect sense to me (because
p
is a function pointer, its dereferenced value is the function, we call the function, it returns 5, we print 5). I was very surprised to find that (6) prints 5 as well! Why is this?Similarly, lines (7)--(10) all print the same value, namely
&ret_five
. Why does (10) work?Lines (11) and (12) print the same value, namely the address where the first element of
x
lives in memory. Line (12) makes sense, but I don't quite understand exactly what is technically happening in line (11). Doesx
automatically get cast or interpreted as anint*
in this context?To get the location in memory where
x
is stored, I typically do&x[0]
, but it seems like&x
works just fine as well, and becausex
is an array and not a pointer, it seems like in fact&x
may be the more canonical way of getting this memory address. Is there a reason to prefer one to the other?In general, are there best-practices in the above situations? For example, if
p = ret_five;
andp = &ret_five
really do the exact same thing, is there a reason to prefer one to the other?And, if the two assignments in question 7 really do the exact same thing, why, in a language that is otherwise so rigid, was this laxity built-in?