I am a teaching assistant of a introductory programming course, and some students made this type of error:
char name[20];
scanf("%s",&name);
which is not surprising as they are learning... What is surprising is that, besides gcc warning, the code works (at least this part). I have been trying to understand and I wrote the following code:
void foo(int *v1, int *v2) {
if (v1 == v2)
printf("Both pointers are the same\n");
else
printf("They are not the same\n");
}
int main() {
int test[50];
foo(&test, test);
if (&test == test)
printf("Both pointers are the same\n");
else
printf("They are not the same\n");
}
Compiling and executing:
$ gcc test.c -g
test.c: In function ‘main’:
test.c:12: warning: passing argument 1 of ‘foo’ from incompatible pointer type
test.c:13: warning: comparison of distinct pointer types lacks a cast
$ ./a.out
Both pointers are the same
Both pointers are the same
Can anyone explain why they are not different?
I suspect it is because I cannot get the address of an array (as I cannot have & &x
), but in this case the code should not compile.
Edit: I know that an array by itself is the same as the address of the first element, but this is not related to this problem, I think. For example:
int main() {
int a[50];
int * p = a;
printf("%d %d %d\n", p == a, p == &a[0], &p[0] == a);
printf("%d %d %d\n", p == &a, &p == a, &p == &a);
}
prints:
$ ./a.out
1 1 1
1 0 0
I don't understand why the second line begins with 1
.
In your example, the array test
is a block of 50 ints
. So it looks like this:
| int | int | ... | int |
When you apply the unary &
operator to an array, you get the address of the array. Just like when you apply it to anything else, really. So &test
is a pointer that points to that block of 50 ints
:
(&test) -----------> | int | int | ... | int |
A pointer that points to an array of 50 ints has type int (*)[50]
- that's the type of &test
.
When you just use the name test
in any place where it's not the operand of either the sizeof
or unary-&
operators, it is evaluated to a pointer to its first element. So the test
that you pass to foo()
evaluates to a pointer to the test[0]
element:
(test) -----------------\
v
(&test) -----------> | int | int | ... | int |
You can see that these both are pointing to the same address - although &test
is pointing to the whole array, and test
is pointing to the first element of the array (which only shows up in the different types that those values have).