Usage of typedef
1. Basic Concepts
Int * (* A [5]) (INT, char *); // #1
Void (* B [10]) (void (*) (); // #2
Double (*) (* pA) [9]; // #3
1. function declaration and array declaration in C language. The function declaration is generally like this:
Int fun (INT, double );
The Declaration of the corresponding function pointer (pointer to function) is as follows:
INT (* PF) (INT, double );
It can be used as follows:
PF = & fun; // assignment operation
(* PF) (5, 8.9); // function call operation
Note that the C language provides the following shorthand:
PF = fun; // assignment operation
PF (5, 8.9); // function call operation
However, I am not very fond of this shorthand, and it brings a lot of confusion to beginners.
The array declaration is generally like this:
Int A [5];
The Declaration of the array pointer (pointer to array) is as follows:
INT (* pA) [5];
It can be used as follows:
Pa = & A; // assignment operation
Int I = (* pA) [2]; // assign a [2] to I;
2. With the above foundation, we can deal with the first three paper tigers! :) At this time, you need to review the priority and combination sequence of various operators. By the way, it is enough to look for a book.
#1: int * (* A [5]) (INT, char *);
First, we can see that the identifier name A has a higher priority than "*", and a is combined with "[5. Therefore, a is an array with five elements. Each element is a pointer,
The Pointer Points to "(INT, char *)", right, pointing to a function. The function parameter is "int, char *", and the return value is "int *". After that, we killed the first paper tiger. :)
#2: void (* B [10]) (void (*)());
B is an array with 10 elements. Each element is a pointer pointing to a function. The function parameter is "void (*) ()" [NOTE 1 ], the return value is "Void ". Finished!
Note 1: This parameter is a pointer pointing to a function. The function parameter is null and the return value is "Void ".
#3: Double (*) (* pA) [9];
Pa is a pointer pointing to an array with nine elements. Each element is "Double (*) ()" (that is, a pointer pointing to a function, the function parameter is null and the return value is "double "]. (Note the difference between typedef int * P [9] And typedef int (* P) [9]. The former defines an array, which contains 9 int * type members, the latter defines a pointer to an array. The directed array contains nine int-type members ).
Do you think it is easy to know them? To do something nice, you must first sharpen your skills! Once we are familiar with this expression, we can use "typedef" to simplify this type declaration.
#1: int * (* A [5]) (INT, char *);
Typedef int * (* PF) (INT, char *); // PF is a type alias [NOTE 2 ].
Pf a [5]; // same effect as int * (* A [5]) (INT, char!
NOTE 2: Many beginners only know typedef char * pchar, but do not know much about other usage of typedef. Stephen blha summarized the usage of typedef: "The method to create a type alias is simple. In a traditional variable declaration expression, replace the variable name with the type name, then, add the keyword typedef to the beginning of the statement ".
#2: void (* B [10]) (void (*)());
Typedef void (* PFV )();
Typedef void (* pf_taking_pfv) (PFV );
Pf_taking_pfv B [10]; // the same effect as void (* B [10!
#3. Double (*) (* pA) [9];
Typedef double (* PF )();
Typedef PF (* pA) [9];
Pa; // the same effect as Doube (*) (* pA) [9!
3. Position of const and volatile in type declaration.
here I only say that const and volatile are the same! [NOTE 3]
Note 3: As the name suggests, the volume modified by volatile is a variable and unstable volume, which may be modified by other threads, operating systems, hardware changes at unknown times.
therefore, it is stored in the memory and can only be read in the memory each time it is used, it cannot be placed in internal registers by Compiler optimization.
In the type declaration, const is used to modify a constant. We generally use const as follows:
const int; // Int Is const
const char *; // char is const
char * const; // * (pointer) is const
const char * const; // both char and * are const
for beginners, const char * and char * const are easy to confuse. It takes time for you to get used to it. The preceding statement has the following equivalent statement: const:
int const; // Int Is const
char const *; // char is const
char * const; // * (pointer) is const
char const * const; // char and * are both const
you may not get used to it for the first time, but if new things are good, why should we reject them? :) Const has two advantages:
the type modified by A. const is exactly the one before it. If this benefit does not motivate you, please refer to the next one!
B. We often use the typedef type alias definition. For example, if typedef char * pchar is modified using const,
when const is in front of const, It is const pchar. You will think it is const char *, but you are wrong, its true meaning is char * Const.
did it surprise you! However, if you use the const statement, the meaning will not change. If you don't believe it, try it!
however, naming consistency in real projects is more important. You should be able to adapt in both cases and switch freely. Company habits:
commercial profits should be given priority at any time! However, when starting a new project, you can prioritize the usage of const in the future.
2. typedef statements help you create platform-independent types and even hide complex and incomprehensible syntaxes.
However, if typedef is used Code It brings unexpected benefits. Through this article, you can learn to use typedef to avoid missing ones and make the code more robust.
Typedef declaration, or typedef for short, creates a new name for an existing type. For example, typedef is often used to write more beautiful and readable code.
The so-called beauty means that typedef can hide clumsy Syntax structures and platform-related data types to enhance portability and future maintainability.
In this article, we will do our best to reveal the powerful functions of typedef and how to avoid some common traps, create platform-independent data types, and hide clumsy and incomprehensible syntaxes.
Typedef is used to create a type name that is easy to remember and archive it. Program Member's intention. The type appears in the declared variable name, which is on the right of the typedef keyword.
Example: typedef int size;
This statement defines an int synonym with the name size. Note that typedef does not create a new type. It only adds a synonym for an existing type.
You can use size in any context that requires an int:
Void measure (size * psz );
Size array [4];
Size Len = file. getlength ();
Typedef can also conceal composite types, such as pointers and arrays. For example, you do not need to repeatedly define an array with 81 characters as follows:
Char line [81]; char text [81];
Define a typedef. Whenever an array of the same type and size is used, you can do this:
Typedef char line [81];
Line Text, secondline;
Getline (text );
Similarly, you can hide the pointer syntax as follows:
Typedef char * pstr;
Int mystrcmp (pstr, pstr );
This will take us to the first typedef trap. The standard function strcmp () has two parameters of the const char * type. Therefore, it may mislead people to declare as follows:
Int mystrcmp (const pstr, const pstr );
This is incorrect. In fact, const pstr is interpreted by the compiler as char * const (a constant pointer to Char) rather than const char * (pointer to constant char ).
This problem can be easily solved:
Typedef const char * cpstr;
Int mystrcmp (cpstr, cpstr );
The typedef behavior discussed above is a bit like the # define macro, which replaces the synonym with its actual type. The difference is that typedef is interpreted during compilation.
Therefore, let the compiler handle text replacement that exceeds the pre-processor capability. For example:
Typedef int (* PF) (const char *, const char *);
This statement introduces the PF type as the synonym of the function pointer. This function has two parameters of the const char * type and a return value of the int type. If you want to use the following form of function declaration, the above typedef is indispensable:
PF register (PF );
The Register () parameter is a PF type callback function that returns the address of a function with the same signature as the previously registered name. Take a deep breath. The following shows how to implement the declaration without typedef:
INT (* Register (INT (* PF) (const char *, const char *) (const char *, const char *);
Few programmers understand what it means, not to mention the risk of errors caused by such obscure code. Obviously, using typedef here is not a kind of privilege,
It is a necessity. Typedef is like auto, extern, mutable, static, and register. It is a storage keyword.
This does not mean that typedef will really affect the Storage Feature of objects; it only means that in the statement structure, typedef statements look like static, extern and other types of variable declarations.
The following is a second trap:
Typedef register int fast_counter; // The Error Code cannot be translated.
The problem is that you cannot have multiple storage-class keywords in the Declaration. Because the symbol typedef occupies the storage class keyword,
Register (or any other storage-class keywords) cannot be used in the typedef declaration ). Another important purpose of typedef is to define machine-independent types,
For example, you can define a floating point type called real to obtain the highest precision on the target machine:
Typedef long double real;
On a machine that does not support long double, the typedef looks like the following:
Typedef double real;
In addition, on a machine that does not support double, the typedef looks like this:
Typedef float real;
You do not needSource codeWith any modifications, You can compile this real-type application on each platform. The only change is typedef itself.
In most cases, even this tiny change can be automatically implemented through fantastic Conditional compilation. Isn't it?
The standard library uses typedef to create such platform-independent types: size_t, ptrdiff, and fpos_t.
In addition, typedef, such as STD: string and STD: ofstream, also hides long, incomprehensible template-specific syntax,
For example, basic_string, Allocator>, and basic_ofstream>.