Use structure pointer or not when using typedef in C

To define a new data type in C, for example a type for a linked list
, you can use one of the following definitions

struct list_node { int x; struct list_node * next; }; //1 typedef struct list_node list1; //2 typedef struct list_node *list2; 

From what I saw, common practice is the first definition.

The question is whether the second definition is acceptable practice. In what cases, if someone prefers the second over the first? Given that the variables we use are pointers to a struct list_node, is it possible to perform the same operations with both types? What are the advantages of the first?

+6
c list pointers struct typedef
source share
5 answers

I would ask API users to enter "*", i.e. typedef struct, not a pointer to a structure. This is a widely used style in GLib, which is one of C's most popular stacks.

This works well because it is important to know if you have a pointer to a structure or a structure. For example, can you store NULL in a type variable? If you hide that the object is a pointer, you need to create a special NIL_NODE or another value to replace NULL. If you just make it a pointer, then people can treat it as one.

Another important advantage is the ability to put the actual definition of the structure somewhere private, that is, in the .c file, and not in the header. You can only put typedef in the header, while keeping the structure opaque to users of the API. This requires people to use only the exported methods that you provide for structure management. It also means that you do not need to restore the world if you change the structure fields.

Another reason for this path is that sometimes you need a structure that can be copied, and you still want to print it. Take something like GdkPoint:

  typedef struct { int x, y; } GdkPoint; 

It is useful to allow direct access to the structure, for example:

  GdkPoint point = { 10, 10 }; GdkPoint copy = point; do_stuff_with_point(&copy); 

However, if your convention is that typedef "GdkPoint" be a pointer, you will have to be inconsistent.

The code is simply clear if you can indicate which pointer and what is not, and the code is better encapsulated if you do not put the definition of struct in the header (for structures that represent abstract, opaque data types, which is probably the most common type).

My default template for the data type C in the header looks something like this:

 typedef struct MyType MyType; MyType* my_type_new(void); void my_type_unref(MyType *t); void my_type_ref(MyType *t); 

Then the actual "struct MyType" in the .c file, as well as the new, unref and any type operations.

An exception will be for such types as Point, Rectangle, Color, where "simple old data" and direct access to fields are desirable; another option is to have my_type_free () instead of _unref () if you don't need a recount.

In any case, this is one style, mainly the GLib style, which is widely used and, as you know, works well.

+5
source share

I prefer the first style, so it determines which types are objects and which are pointers. But I find that C pointers are easy to understand / interpret, which (apparently) many people don't. Therefore, if you think that most people reading your code base will not understand pointers, use typedef STRUCT_FOO *PSTRUCT_FOO everywhere, as the Win32 API does.

+1
source share

Consider using both of these:

 typedef struct list_node Node; typedef Node* ListHead; 
0
source share

As long as the identifier clears it with a pointer, then there is no harm (I personally prefer the suffix ala _Pointer or _Ptr, but whatever suits the project). However, there is no real benefit to C code to avoid explicit * . For mixed C / C ++ or pure C ++ environments, I often saw the use of typedef for streamlined / reasonable pointers, making it easy to switch to, use and switch between types of smart pointers. There is probably some truth to this, although I never found that I want to accept this practice.

0
source share

typedef int * ptr_int; ptr_int x, y, z;

The programmer may be confused by the fact that all three x, y, z are of type int *. Pointers to int. But in Reality, only x is of type int * y and z is simple int.

because ptr_int x, y, z; equal to int * x, y, z; not int * x, * y, * z;

Thus, typedef also creates confusion in the minds of programmers and can lead to errors and errors.

0
source share

All Articles