Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are typedef names used twice in struct declaration in C?

Tags:

c

struct

typedef

While researching queues in C, I came across an example similar to the below. Why is the struct named both at the beginning of the curly braces and after? Why is struct type used again inside of the struct when adding an item of the same type? Are these things redundant or is there a point?

typedef void* vpoint_t;

typedef struct queue_item_t{
  vpoint_t void_item;
  struct queue_item_t* next;
} queue_item_t;
like image 478
CompSci-PVT Avatar asked Sep 04 '15 19:09

CompSci-PVT


People also ask

Can typedef and struct have same name?

You can't "typedef a struct", that doesn't mean anything.

Why do you use typedef in a structure?

The C language contains the typedef keyword to allow users to provide alternative names for the primitive (e.g.,​ int) and user-defined​ (e.g struct) data types. Remember, this keyword adds a new name for some existing data type but does not create a new type.

What is the difference between typedef struct and struct in C?

Basically struct is used to define a structure. But when we want to use it we have to use the struct keyword in C. If we use the typedef keyword, then a new name, we can use the struct by that name, without writing the struct keyword.

Can we typedef in declaring structure?

You can declare a typedef name for a pointer to a structure or union type before you define the structure or union type, as long as the definition has the same visibility as the declaration. Typedef names can be used to improve code readability.


1 Answers

typedef struct queue_item_t {     // 1
  vpoint_t void_item;
  struct queue_item_t* next;      // 2
} queue_item_t;                   // 3

First of all, note that this entire statement is defining a typedef.

3) Is saying that the new type we are in the process of defining (via typedef) is going to be named queue_item_t.

1) The name of the structure (which is being given a new name, as we go), is named struct queue_item_t. That's it's full name, including struct at the front.

2) Because the new type doesn't yet exist (remember, we're still in the process of defining it), we have to use the only name it has thus far, which is struct queue_item_t, from 1).


Note that you can have anonymous struct definitions, which allow you to omit the name from 1). A simple example:

typedef struct {
   int x, y, z;
} vector3;

In your example however, since we need the structure to be able to refer to itself, the next pointer must have a type that's already defined. We can do that by forward declaring the struct, typedefing it, then defining the struct using the typedefd type for next:

struct _queue_item;                           // 4

typedef struct _queue_item queue_item_t;      // 5

struct _queue_item {                          // 6
  vpoint_t void_item;
  queue_item_t* next;                         // 7
}

4) Declare that struct _queue_item exists, but don't yet provide a definition for it.

5) Typedef queue_item_t to be the same as struct _queue_item.

6) Give the definition of the structure now...

7) ...using our typedef'd queue_item_t.


All that being said... In my opinion, please don't use typedefs for structs.

struct queue_item {
    void *data;
    struct queue_item *next;
}

is simple and complete. You can manage to type those six extra characters.

From the Linux Kernel coding style:

Chapter 5: Typedefs

Please don't use things like "vps_t". It's a mistake to use typedef for structures and pointers. When you see a

  vps_t a;

in the source, what does it mean? In contrast, if it says

  struct virtual_container *a;

you can actually tell what "a" is.

There are exceptions, which you can read about.


Some recent related questions:

  • Why use an opaque “handle” that requires casting in a public API rather than a typesafe struct pointer?

  • Does casting a pointer back and forth from size_t or uintptr_t break strict aliasing?

like image 184
Jonathon Reinhart Avatar answered Nov 14 '22 21:11

Jonathon Reinhart