2

I need some help to understand this struct:

typedef struct std_fifo{
    char* name;
    struct std_fifo* next;
}std_fifo, *fifo;

With typedef I know that I can use only std_fifo instead of writing struct std_fifo in my code. But what about the *fifo?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
iAmoric
  • 1,787
  • 3
  • 31
  • 64
  • This means you can write `fifo variablename;` instead of `struct std_fifo *variablename;` or `std_fifo *variablename;` to declare a pointer to the struct. – mch Nov 29 '16 at 16:53
  • So I can write 'fifo variablename;' or 'std_fifo *variablename;' ? Is it the same ? – iAmoric Nov 29 '16 at 16:57
  • 6
    See [Is it a good idea to typedef pointers](http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers) — succinct answer: No. – Jonathan Leffler Nov 29 '16 at 16:57
  • 1
    `typdef`ing pointers is very bad style in C. Don't do it! – too honest for this site Nov 29 '16 at 17:02
  • @JonathanLeffler, Why comma is required between std_fifo and *fifo? – MayurK Nov 29 '16 at 17:03
  • 1
    @MayurK: Two separate typedef names being defined. Equivalent to: `struct std_fifo { char* name; struct std_fifo* next; }; typedef struct std_fifo std_fifo; typedef struct std_fifo *fifo;`. In this fragment, you can reorder the three statements in any sequence you prefer. – Jonathan Leffler Nov 29 '16 at 17:04
  • 1
    Re "Why comma is required between std_fifo and *fifo": For the same reason it's required in `int i1, i2;`: The language demands it when several identifiers are declared in a single declaration. Because spaces cannot be part of an identifier I suppose one could do without the commas, so consider it [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) for the casual human reader ;-). – Peter - Reinstate Monica Nov 29 '16 at 17:22

2 Answers2

3

The code

typedef struct std_fifo{
    char* name;
    struct std_fifo* next;
}std_fifo, *fifo;

creates two (very badly named) typedef names, std_fifo and fifo.

The typedef name std_fifo is equivalent to the type struct std_fifo, and can be used in place of struct std_fifo:

std_fifo fifo_instance;      // creates an instance of struct std_fifo
std_fifo get_fifo();         // declares get_fifo as a function returning an 
                             // instance of struct std_fifo
void read_fifo( std_fifo * );// declares a function taking parameter of type
                             // pointer to struct std_fifo

The typedef name fifo is equivalent to the type struct std_fifo *, and can be used in place of struct std_fifo *:

fifo fifo_ptr;               // creates a pointer to an instance of struct std_fifo
fifo get_fifoptr();          // declares get_fifoptr as a function returning a pointer
                             // to an instance of struct std_fifo
void read_fifo( fifo );      // declares a function taking a parameter of type
                             // struct std_fifo *

The reason code like

typdef struct std_fifo { ... } std_fifo;

works is because C has four different name spaces for identifiers: labels, tag names, struct and union member names, and everything else. The tag name std_fifo is always preceded by the struct keyword, which is how the compiler distinguishes it from the std_fifo typedef name.

Some advice on using typedefs:

While they can help your code scan better in some cases, using typedefs can actually obscure your intent and make types harder to use. If the user of the type has to be aware of its representation (such as to access a member of a struct, or dereference a pointer type, or to use the right conversion specifier in a printf or scanf call, or to call a function propertly, etc.), then you should not hide the representation behind a typedef.

If you decide you do want to hide a type's representation behind a typedef, then you should also provide a full API for any operations involving that type. C does this with the FILE type; instead of manipulating a FILE object directly, you pass a pointer to it to the various stdio routines. So, if you decide you want to hide struct std_fifo * behind the typedef name fifo, then you should also create an API like:

fifo new_fifo();                // create a new fifo queue
void destroy_fifo( fifo * );    // destroy an existing fifo queue
set_name( fifo, const char * ); // set the name of a fifo element 
char *get_name( fifo );         // retrieve the name of a fifo element
fifo push_fifo( fifo );         // add an element to the end of the queue
fifo pop_fifo( fifo );          // remove an element from the front of the queue

Abstraction can be a Good Thing, but "leaky" abstractions are worse than no abstraction at all.

John Bode
  • 119,563
  • 19
  • 122
  • 198
1

It is a valid definition of struct to give either with a name and with a pointer.

typedef struct std_fifo{
    char* name;
    struct std_fifo* next;
}std_fifo, *fifo;

In this code, where std_fifo is a struct and *fifo is the pointer to this struct.

I would strongly suggest you to take a look at here : http://www.cplusplus.com/forum/windows/57382/

Prometheus
  • 1,522
  • 3
  • 23
  • 41
  • Note that `std_fifo` is an alias for the type name of a structure type, and `fifo` is an alias for a pointer type that points to the same structure type. Your commentary makes it appear a bit as if you think they are variables. If you replaced the storage class `typedef` with `static` or `extern`, then indeed the fragment would define or declare a pair of variables. With the 'storage class' of `typedef`, it defines aliases for the type `struct std_fifo`. – Jonathan Leffler Nov 29 '16 at 17:52
  • Yes and I already told that it is a **struct**. I didn't say that it is the name of the struct variable name or any other thing? @JonathanLeffler – Prometheus Nov 29 '16 at 18:27
  • OK. I'll leave it at "I find your language ambiguous" but you know what you mean. – Jonathan Leffler Nov 29 '16 at 18:55