41

I'm trying to understand struct in C. I couldn't get the idea about this definition below. Why do we leave aCard, deck[ ] and *cardPtr out? What is the difference between including them in and leaving them out?

 struct card {
    char *face;
    char *suit;
 } aCard, deck[52], *cardPtr;
Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
Belverus
  • 623
  • 6
  • 10
  • 1
    Think of it this way: the deck, per example is not the property of a card. A card can exist on its own without a deck. So the deck is not part of `card`. – Blaze Oct 17 '18 at 09:29
  • 15
    It's just sloppy declaration style, combined with using "Linux style" structs instead of the more commonly used `typedef struct { } card_t;`... `card_t card;` – Lundin Oct 17 '18 at 10:00
  • 8
    The code is hard to read, not intuitive, functionally correct but not as readable as how @MichaWiedenmann rewrite. Readable code is more important. – Trevor Boyd Smith Oct 17 '18 at 11:50
  • 2
    @Lundin Or even just `struct card { ... }` ... `struct card drawn;` (Which is what I prefer, but it's more a style thing) – Nic Oct 17 '18 at 16:58
  • 1
    consider: `struct human {face_t* face, torso_t* torso, arms_t* arms, legs_t* legs} Belverus;`. What's the difference between face/torso/arms/legs and Belverus? – Mooing Duck Oct 17 '18 at 21:05
  • 2
    @Lundin: There are [good reasons _not_ to typedef structs](https://stackoverflow.com/a/4566358). It’s not “sloppy”; [Linux does it for a reason](https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs). – wchargin Oct 18 '18 at 01:15
  • Possible duplicate of [c++ - What does the name after the closing class bracket means?](https://stackoverflow.com/questions/17843145/c-what-does-the-name-after-the-closing-class-bracket-means) --- actually that is for c++ not c, but the syntax is inherited. – user202729 Oct 18 '18 at 01:31
  • There is also https://stackoverflow.com/questions/16057238/defining-structure-variable-after-structure-type - but it's about a different problem. – user202729 Oct 18 '18 at 01:33
  • 1
    @wchargin: read their comment again. Lundin said it is sloppy and typedef-free, not sloppy _because_ it is typedef free. In my opinion, what's sloppy here is the combined struct layout and variable declaration. – Eric Oct 18 '18 at 05:53
  • @wchargin If you read my comment again, you'll find that the sloppy part refers to the variable declarations and not the struct style. That being said, the Linux kernel style guide is an amateur-level document, completely without rationale or sources. Notably, the link offered provides no rationale, just opinions. And so the Linux kernel is about as far from canonical C as you can get, filled with reliance on poorly-defined behavior and non-standard extensions. If you want serious coding guidelines for professionals, use MISRA or CERT. – Lundin Oct 18 '18 at 06:23
  • You are not leaving nothing - struct followed by tag name and optionally followed by curly braces is part of the type. – AnArrayOfFunctions Nov 02 '18 at 19:11

6 Answers6

74

You are mixing things up. A struct card has the members face and suit. But there are three variables using the struct card type, namely aCard, deck, cardPtr.

Alternatively one could have written:

typedef struct {
    char *face;
    char *suit;
} Card;

Card aCard, deck[52], *cardPtr;
// or even
Card aCard;
Card deck[52];
Card *cardPtr;

For the typedef have a look at: Why should we typedef a struct so often in C? (It goes into the typedef struct { ... } Foo; vs struct Foo {...} debate).

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
  • Yes, the to-typedef or not-to-typedef debate rages on. But why introduce something that wan't present in the original question? It just complicates the answer. Sorry, but I'm downvoting for this reason, and upvoting [Jabberwocky's answer instead](https://stackoverflow.com/a/52851603/119527). – Jonathon Reinhart Oct 18 '18 at 14:42
28

Your piece of code could be written like this which makes it clearer:

struct card {          // define the struct card
    char *face;
    char *suit;
 };

struct card aCard;     // declare a variable "aCard" of type "struct card "
struct card deck[52]   // declare an array of 52 variables of type "struct card"
struct card *cardPtr;  // declare a variable "cardPtr" of type "pointer to struct card"
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
20

Though, this question has already answered, I am posting my answer because I think the OP has doubt in structure declaration and definition of variable of a structure type.

If you don't know what is a structure in C, please have a look at 1) below.

The keyword struct introduces a structure declaration, which is a list of declarations enclosed in braces. An optional name called a structure tag may follow the word struct. Hence, this is a structure declaration:

struct card {
    char *face;
    char *suit;
 };

here face and suit are member variables. Note that a structure declaration reserves no storage; it merely describes a template of a structure.

A struct declaration defines a type. The right brace that terminates the list of members may be followed by a list of variables. So, in your case:

....
} aCard, deck[52], *cardPtr;

aCard, deck[52] and *cardPtr are the variables of type struct card.

Since your structure declaration is tagged with name card, the tag card can be used later in definitions of instances of the structure. e.g. given the declaration of structure card above,

struct card someCard;

defines a variable someCard which is a structure of type struct card.

Alternatively, you can typedef a structure declaration and use it to define variables of its type.


1)

By definition - A structure is a collection of one or more variables, possibly of different types, grouped together under a single name.

As per C standard#6.2.5 [Types]:

A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.

.....
.....
Arithmetic types and pointer types are collectively called scalar types. Array and structure types are collectively called aggregate types.46)

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
H.S.
  • 11,654
  • 2
  • 15
  • 32
  • 1
    Or to put it in a nutshell, the whole "struct foo {...}" in the OP's code is just the same as int or float in "int i, j, k;" or "float x, y, z;". – jamesqf Oct 17 '18 at 17:11
6

A

struct card {
    char *face;
    char *suit;
 }

is just like int, but it is user defined, and

aCard, deck[52], *cardPtr;

are variable names, for example,

int aCard, deck[41], *cardPtr;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BladeMight
  • 2,670
  • 2
  • 21
  • 35
  • 3
    The `struct card` and `int` are indeed both types, but they are not equivalent. I want to clarify this as I think this answer can be misread by some beginners or people not fluent in english. – Robin Goupil Oct 17 '18 at 12:54
1

You have declared three variables. aCard is of type struct card, deck is of type struct card[52] and cardPtr is of type struct card *

klutt
  • 30,332
  • 17
  • 55
  • 95
0

aCard and the rest you have mentioned are variables of type struct card and each of these variables contain char *face and char *suit. So how can some variable can contain itself i.e. aCard being inside the struct node.

Gaurav
  • 1,570
  • 5
  • 17