2

Given:

typedef Card* Cardptr;

Does this mean that foo in the following declaration

Cardptr foo;

is the same as in this declaration?:

struct Card{

} *foo;

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

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Marcus Kim
  • 283
  • 2
  • 12
  • No. Really, no. `typedef` introduces an alias for an already existent type. There is no way you can use it to define a class. – skypjack Aug 31 '17 at 05:18
  • 3
    The answers are different for C and C++ — which are you asking about? – Jonathan Leffler Aug 31 '17 at 05:29
  • @JonathanLeffler: that's interesting - hoping you'll elaborate on the differences actually, rather than narrow the question. It's not unusual that people need this kind of code in a header to be included from both languages, so it's not inherently unreasonable to tag the question with both. – Tony Delroy Aug 31 '17 at 05:34
  • @TonyDelroy: At one level, it's not that exciting. In C, you'd have to write `typedef struct Card Card;` before you can use `typedef Card *Cardptr;`; in C++, it suffices to use `struct Card;` before `typedef Card *Cardptr;`. The difference is important, but not exciting. The C notation works in C++; the C++ notation doesn't work in C. But C++ does not need the C notation. – Jonathan Leffler Aug 31 '17 at 05:40
  • @JonathanLeffler: ah yes - the separate naming space for structs - hadn't twigged it kicked in that way here. Been decades since I've had to program C. Thanks for the explanation. – Tony Delroy Aug 31 '17 at 05:45
  • 2
    Also, using a typedef to hide the `*` can easily be confusing. `Card*` is pretty obvious, and less typing. [Is it a good idea to typedef pointers?](https://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers?noredirect=1&lq=1) – Bo Persson Aug 31 '17 at 10:04

2 Answers2

2

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • My book says `typedef Card* Cardptr;` "defines the new type name `Cardptr` as a synonym for type `Card*`." From what you're saying, I see that `*` symbol modifies `Cardptr` and that other synonyms, if there were any more, are not modified by `*` symbol. This is confusing to me. My book makes it seem like the actual structure type is `Card*`, which makes me think that other synonyms would have the type `Card*` as in `typedef Card* Cardptr, n;` where `n` would also have the type `Card*`. Wouldn't it be clearer if they moved `*` symbol like this `typedef Card *Cardptr, n;`? – Marcus Kim Sep 01 '17 at 00:26
  • 2
    @MarcusKim - It would be clearer. In fact, your confusion and its prevention are a major argument for this coding style (which I personally follow) that places the asterisk next to the identifier. The argument in the other way is that the modification is always on the type of the entity. Coding style aside, just remember that is modifies the type of the new identifier (Makes the variable `i` a pointer in `int *i, j;` and the alias `CardPtr` another name for a pointer type in `typedef Card *CardPtr, n;`). – StoryTeller - Unslander Monica Sep 01 '17 at 20:09
0

[for C++] Yes: you can create a variable foo that's a Card* at the tail end of the struct Card definition as you've illustrated, and it's equivalent to the Cardptr foo above (assuming an earlier definition of Card) as in:

struct Card {

};
typedef Card* Cardptr;
Cardptr foo;

People sometimes do the trailing *foo thing for concision - it avoids having to repeat the type.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • You might want to add, that your answer addresses C++ only. It is not valid for C. – alk Aug 31 '17 at 08:39