ANSI C - The Benefit of Assigning an Alternate Name to a Pointer Type Using Typedef

Possible duplicate:
What is the correct way for a typedef of type and a pointer of the same type?

I recently used Libxml2 in my project and noticed that it uses typedefs as shown below:

typedef struct _xmlNode xmlNode typedef xmlNode * xmlNodePtr 

The advantage of the first typedef is obvious. However, I'm not sure why you assigned the alternate name xmlNode *. For me it is more explicit and readable to use xmlNode * than to use xmlNodePtr , but I might be missing something.

What problems will this typedef solve and what benefits will it bring?

+4
source share
4 answers

What problems will this typedef solve and what benefits will it bring?

My opinion is to typify object pointers, and this should not be done.

First, it changes the C grammar, hiding that the declared object has a pointer type.

Secondary classifiers ( const and volatile ) cannot penetrate a typedef.

If you take your example:

 typedef struct _xmlNode xmlNode; typedef xmlNode * xmlNodePtr; 

It is now impossible to declare an object, so pointee const uses the alias xmlNodePtr .

 const xmlNodePtr xp; 

means xp is const not *xp .

 const xmlNode x = /* ... */; const xmlNodePtr xp = &x; // Error! 

By the way, in the Linux kernel coding style, they also do not recommend using typedef for pointers:

"It is a mistake to use typedef for structures and pointers."

+1
source
APIs

C often provide opaque pens that prevent the consumer from asking what they are and trying to stick it out. The fact that these pens are pointers does not matter and does not matter to the consumer, and should not be burdened with lexical interference of an additional star.

For example, it is possible to write a C ++ binding by specifying a handle:

 typedef void * MyHandle; 

Now we give blessed user C some functions:

 MyHandle create_gizmo(); void destroy_gizmo(MyHandle); int do_magic(MyHandle, int, int); 

Just. The user immediately sees how to use it:

 #include "MagicAPI.h" MyHandle h = create_gizmo(); submit_result(do_magic(h, 12, 91)); destroy_gizmo(h); 

And the C ++ library developer simply expands the descriptor and populates the API functions (which, of course, are extern "C" declared):

 #include "MagicAPI.h" #include "SuperGizmo.hpp" MyHandle create_gizmo() { return static_cast<MyHandle>(new SuperGizmo); } void destroy_gizmo(MyHandle h) { delete static_cast<SuperGizmo *>(h); } int do_magic(MyHandle h, int a, int b) { return static_cast<SuperGizmo *>(h)->foo(a, b); } 
+2
source

For some people, a typedef with โ€œptrโ€ in the title is more readable and โ€œnaturalโ€ than declarations using standard pointer syntax. If you like to write

 foo* p; 

instead

 foo *p; 

then the typedef pointer will most likely turn to you because it specifically avoids write errors

 foo* p, q; 

when did you mean

 foo *p, *q; 

Instead you can write

 fooptr p, q; 
+1
source

There are several differences.

First, if you are making multiple declarations on the same line, the following two fragments are equivalent:

 char *c1, *c2, *c3, *c4; typedef char * charPtr; charPtr c1, c2, c3, c4; // I don't need to repeat the unary * everywhere 

This is useful in part because you may run into semantic problems when trying to do something like:

 char * c1, c2, c3, c4; // declares one char pointer and three chars 

Secondly, they can greatly simplify the definition of types of function pointers, which are possibilities for almost infinite ugliness and muck.

 float (*someCrazyFunction)(float(*)(), float) = foo; // WTF is this typedef float (*crazyFunction)(float(*)(), float); crazyFunction myCrazyFunction = foo; // easier to deal with 

Here is an ideon demonstrating all this behavior.

0
source

Source: https://habr.com/ru/post/1434707/


All Articles