Does this mean that foo in the following declaration ... is the same as in this declaration? ...
Yes and no. I say yes because both declarations declare a pointer variable to the type named Card
(in C++, for C to apply as well, it must be struct Card
). But it's not exactly the same.
The first declaration can introduce what is called an "opaque handle". The struct doesn't need to be fully defined at that point. You can pass pointers to it around, but you won't be able to access any members until the full definition is seen.
The second declaration introduces the complete type and immediately creates a pointer to it. It's equivalent to the first case after the full structure definition is seen.
The appearance of the *
symbol has me confused because it appears adjacent to Card
in the statement that we're given and appears adjacent to foo
in the statement with *foo
The adjacency of *
is immaterial. Since it's applied the same regardless of where you write it. It modifies the newly declared entity, not the type. To illustrate:
int *i, j;
Will create only one pointer, named i
, and a regular integer named j
. Since typedef
statements follow the same rules as variables declarations (the application of the typedef
keyword just changes the meaning from introducing a new object, to introducing a new type name), the behavior of *
is equivalent. Meaning that here:
typedef int *i, j;
The *
again modifies only i
. We end up with two aliases. The alias i
which is a new type name for a pointer to an int
, and j
which is an alias for an int
.
In fact, we could have rewritten it as follows to get the same effect:
typedef int j, *i;
Again, because *
modifies only i
.