6

The following blocks are outside of main() and before every function (global scope)

1st block:

struct flight {
    int number;
    int capacity;
    int passengers;
};

With this you can create array,pointer,variable in contrast with writing } var; (which defines only one variable of this custom data type (struct flight))

2nd block:

typedef struct flight {
    int number;
    int capacity;
    int passengers;
} flight;

Declaring this creates a data type flight without having to write struct flight all the time
My question is why typedef needs flight to be written a second time at the end of a block?
which is a bit confusing (it looks like only a variable of that datatype)

solid.py
  • 2,782
  • 5
  • 23
  • 30
  • 2
    Consider: `typedef unsigned char uint8_t;` — the type name introduced is `uint8_t` and the base type it aliases is `unsigned char`. Now consider: `typedef struct flight flight;` — the type name introduced is `flight` and the derived type it aliases is `struct flight`. If `struct flight` had not been mentioned before, this also introduces the type `struct flight` as an opaque structure type. You could subsequently define the type with `struct flight { ... };`. C++ does without the need for the typedef of a structure type, but original C did not have that facility and it has never been added. – Jonathan Leffler Jan 16 '14 at 22:26
  • There is no global scope in C, I think you meant *file scope*. – ouah Jan 16 '14 at 22:26
  • @ouah: There's nothing *called* global scope in C, but it's not a horribly bad name for what the standard calls file scope. (Yes, calling it "file scope" is better.) – Keith Thompson Jan 16 '14 at 22:39
  • 1
    @KeithThompson it's not only a terminology issue: if "global variables" or "global scope" existed, I would expect that an object declared in this scope would be visible in the scope of all translation units. – ouah Jan 16 '14 at 22:44
  • To me the more clear way is to write `typedef struct Foo Foo;` then afterwards use your first version. The user can decide whether he wants to write `struct Foo` or just `Foo` when referring to this struct. Some people like to write something slightly different like `typedef struct Foo_ Foo` and then call the struct `struct Foo_` but I personally find that way to be ugly. The struct tag and the typedef are two different things, there's no need to give them different names. – Brandin Jan 16 '14 at 22:47
  • 1
    @Brandin for me the solution (as most as possible) is to follow the Linux kernel style for this particular point and to not use `typedef` for structure types. – ouah Jan 16 '14 at 22:51
  • @Jonathan **If struct flight had not been mentioned before, this also introduces the type struct flight as an opaque structure type. You could subsequently define the type with struct flight** { ... }; Then what is the use of using typedef if we end up using **struct flight** again to define the other objects of this struct type ? – Rohit Saluja Mar 05 '15 at 06:32
  • @RohitSaluja: In my comment, I am postulating that `typedef struct flight flight;` exists somewhere. This identifies that there is a type `struct flight` (which is incomplete; at this stage, the compiler knows nothing about its size or members), and creates an alias for that type called `flight`. You can now write functions which take a `flight *` or return a `struct flight *`, without needing any further information. However, some code, somewhere, is going to manipulate the data fields in the type. For that code, at least, you need `struct flight { …member definitions… };` somewhere. – Jonathan Leffler Mar 05 '15 at 06:46

1 Answers1

14

My question is why typedef needs flight to be written a second time at the end of a block?

When you declare:

typedef struct flight{
    int number;
    int capacity;
    int passengers;
 }flight;

you actually declare two things:

  • a new structure type struct flight
  • a type alias name flight for struct flight.

The reason why the type alias name with typedef appears at the end of the declaration like for any ordinary declaration is because for historical reasons typedef was put in the same specifiers category as storage-class specifiers (like static or auto).

Note that you can just declare:

typedef struct {
    int number;
    int capacity;
    int passengers;
}flight;

without the tag name if you intend to only use the type identifier flight.

ouah
  • 142,963
  • 15
  • 272
  • 331
  • 2
    +1. You said 'if you intend to only use'; you could have said 'and you will only be able to use' — there is no `struct flight` available in the tagless version (unless it is some unrelated structure type, which would be poor coding style, but is far from impossible). – Jonathan Leffler Jan 16 '14 at 22:20
  • 2
    Without the tag name, the type `flight` cannot have members of type `flight*` (because the identifier `flight` isn't visible early enough). – Keith Thompson Jan 16 '14 at 22:24
  • It might also be worth noting that a lot of software often uses the notation: `typedef struct flight { ... } flight_t`, or sometimes `typedef struct flight_s { ... } flight_t`. – Cloud Jan 16 '14 at 23:06
  • @Dogbert but on POSIX systems `*_t` names are reserved by the implementation if any header used by POSIX is included. – ouah Jan 16 '14 at 23:17
  • 1
    @ouah Can you elaborate more on this, or post a link? I've done a fair bit of embedded development (mainly driver dev), and haven't encountered anything that precludes the use of this convention. – Cloud Jan 16 '14 at 23:37
  • @Dogbert see https://books.google.com/books?id=rHyMRyDEG3gC&pg=PA176&lpg=PA176&dq=POSIX+systems+_t&source=bl&ots=vJqmeqNQ7J&sig=SJahDD_AREAqGRzHFCnqkMYhyAg&hl=en&sa=X&ved=0CD4Q6AEwBWoVChMIvcCo_OLlyAIVAXU-Ch2TQAvz#v=onepage&q=POSIX%20systems%20_t&f=false and http://stackoverflow.com/questions/1391447/what-does-the-postfix-t-stand-for-in-c – MCG Oct 28 '15 at 18:19