Usage of C-language typedef

Source: Internet
Author: User

Http://www.cnblogs.com/afarmer/archive/2011/05/05/2038201.html

I. Basic CONCEPT Analysis

int* (*a[5]) (int, char*); # #
void (*b[10]) (void (*) ()); # #
Double (*) () (*PA) [9]; # #


1. function declarations and array declarations in the C language. The function declaration is generally this:  
int fun (int, double);  
the declaration of the corresponding function pointer (pointer to function) is this:  
Int (*PF) (int, double );  
can be used this way:  
PF = &fun;      //Assignment (Assignment) operation  
(*PF) (5, 8.9);//function call operation  
Also note that the C language itself provides a shorthand method as follows:  
PF = fun;       // Assignment (Assignment) operation  
PF (5, 8.9);     //function call operation  
But I don't really like this shorthand, It brings more confusion to beginners.  
Array declarations are generally:  
int a[5]; 
Declaration for array pointers (pointer to array):  
Int (*PA) [5]; 
Can be used this way:  
PA = &a;            // Assignment (Assignment) operation  
int i = (*PA) [2];//assign a[2] to I;

2. With the above foundation, we can deal with the beginning of the three paper Tigers!:) This time you need to review the order of precedence and combination of operators, and by the way, it is enough to find a book.
#1:int* (*a[5]) (int, char*);
First see the identifier name a, "[]" priority is greater than "*", A and "[5]" first combined. So a is an array with 5 elements and each element is a pointer,
The pointer points to "(int, char*)", to a function, the function argument is "int, char*", and the return value is "int*". Finished, we killed the first paper tiger. :)

#2:void (*b[10]) (void (*) ());
b is an array with 10 elements, each of which is a pointer to a function, the function argument is "void (*) ()" "Note 1", and the return value is "void". Complete!
Note 1: This parameter is also a pointer to a function, the function parameter is empty, the return value is "void".


#3:double (*) () (*PA) [9];
The PA is a pointer to an array that has 9 elements, each of which is a "double (*) ()" "or a pointer to a function, the function argument is null, and the return value is" double

---------------------------------------------------------------
#1:int* (*a[5]) (int, char*);
typedef int* (*PF) (int, char*),//PF is a type alias "Note 2".
PF a[5];//with int* (*a[5]) (int, char*);
NOTE 2: Many beginners only know the TypeDef char* PCHAR, but are not familiar with other uses of typedef. Stephen Blaha A summary of typedef usage: "The way to create a type alias is simply to replace the variable name with a type name in a traditional variable declaration expression, and 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]; with void (*b[10]) (void (*) ());


# # #. Double (*) () (*PA) [9];
typedef double (*PF) ();
typedef PF (*PA) [9];
PA pa; Same effect as Doube (*) () (*PA) [9];

The position of 3.const and volatile in the type declaration.
Here I only say const,volatile is the same! "NOTE 3"
Note 3: As the name implies, theamount of volatile modification is very easy to change, the amount of instability, it may be other threads, operating systems, hardware and so on in the unknown time changes ,
So it is stored in memory and can only be read in memory each time it is fetched, and it cannot be placed in the internal register by the compiler optimizations.
The const used in a type declaration modifies a constant, which we generally use: const in front:

const INT;//int is const
Const CHAR*;//CHAR is a const constant pointer, meaning that the object content is constant
char* const;//* (pointer) is a const pointer constant, and the pointer itself is a constant and cannot be changed to point to
Const char* Const;//char and * are both const
For beginners, the const char* and char* const are easy to confuse. It takes time for you to get used to it. The above declaration has a reciprocal notation: const is in the back:
int const;//int is const
Char Const*;//char is a const
char* const;//* (pointer) is a const
Char const* Const;//char and * are both const

For the first time you may not get used to it, but if the new thing is good, why should we reject it? :) const has two benefits in the back:
A The type that the const modifies is exactly the one in front of it . If the benefit doesn't make you tempted, look next!
B Most of the time we use the TypeDef type alias definition. For example, typedef char* PCHAR, if modified with const,

When the const is in the front, is the const PCHAR, you will think it is a const char*, but you are wrong, its true meaning is char* Const.
Is it a surprise to you? But if you use const in the back of the writing, meaning will not change, do not believe you try!
However, naming consistency is more important in real-world projects. However, when starting a new project, you might consider using the const idiom in the back.

Two. typedef declarations help to create platform-independent types, and can even hide complex and difficult-to-understand grammars.
In any case, using typedef can bring unexpected benefits to your code, and through this article you can learn to use typedef to avoid imperfections and thus make your code more robust.
typedef declaration, referred to as TypeDef, creates a new name for an existing type. For example, people often use typedef to write more aesthetically pleasing and readable code.
The so-called aesthetics means that typedef can hide clumsy grammatical constructs and platform-related data types, thus enhancing portability and future maintainability.
In this article, we will do our best to uncover the powerful features of typedef and how to avoid some common pitfalls, how to create platform-independent data types, and hide clumsy and incomprehensible syntax.
the most common use of TypeDef is to create easy-to-remember type namesand use it to archive the programmer's intentions. The type is in the name of the variable being declared and is located to the right of the TypeDef keyword.
For example: typedef int size;
This declaration defines a synonym for int, named size. Note typedef does not create a new type. It simply adds a synonym to the 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 disguise composite types, such as pointers and arrays. For example, you do not have to define an array of 81-character elements as follows:
Char line[81]; Char text[81];
Define a typedef that can be used whenever you want to use an array of the same type and size:
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 toThe first typedef trap. The standard function strcmp () has two const char * type parameters. Therefore, it may mislead people to declare as follows:
int mystrcmp (const PSTR, const PSTR);
This is wrong,in fact, the const PSTR is interpreted by the compiler as char * const (a constant pointer to char) instead of a const char * (pointer to a constant char).
This problem is easy to solve:
typedef const CHAR * CPSTR;
int mystrcmp (CPSTR, CPSTR);
The typedef behavior discussed above is somewhat like a #define macro, substituting its actual type for synonymous words. Different points aretypedef is interpreted at compile time
, so let the compiler cope with the text substitution beyond the preprocessor's capabilities. For example:
typedef int (*PF) (const char *, const char *);
This declaration introduces the PF type as a synonym for the function pointer, which has two const char * type parameters and a return value of type int. This typedef is essential if you want to use the following form of function declaration:
PF Register (pf pf);
The parameter of register () is a PF-type callback function that returns the address of a function whose signature is the same as the name previously registered. Take a deep breath. Let me show you how we can implement this statement without a 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 error caused by this convoluted code. Obviously, using typedef here is not a privilege,
But a necessity.a typedef is like a auto,extern,mutable,static, and the register is a storage class keyword.
This is not to say that typedef really affects the storage characteristics of an object; it simply says that in the statement composition, the typedef declares a variable declaration that looks like a static,extern type.

The following will take you to a second trap:
typedef register INT Fast_counter; Error compiling pass but
The problem is that you cannot have more than one storage class keyword in a declaration. Because the symbol typedef already occupies the location of the storage class keyword,
Register (or any other storage class keyword) cannot be used in a typedef declaration. typedef has another important purpose, which is to define machine-independent types,
For example, you can define a floating-point type called REAL, which can achieve the highest precision on the target machine:

typedef long double REAL;
On a machine that does not support a long double, the typedef looks like this:
typedef double REAL;
And, on a machine that is not even supported by a double, the typedef looks like this:
typedef float REAL;
You can compile this application using the REAL type on each platform without making any changes to the source code. The only thing to change is the typedef itself.
In most cases, even this tiny change can be done automatically with wonderful conditional compilation. Isn't it?
The standard library uses typedef extensively to create such platform-independent types: Size_t,ptrdiff and fpos_t are examples.
In addition, typedef such as std::string and Std::ofstream hide the long, incomprehensible template-specific syntax,
such as:basic_string,allocator> and basic_ofstream>.

Use one:
Defines an alias for a type, not just a simple macro substitution. Can be used as multiple objects that declare a pointer type at the same time. Like what:
char* PA, PB; The majority does not conform to our intent, it only declares a pointer to a character variable,
and a character variable;
The following are possible:
typedef char* PCHAR; General capitalization
PCHAR PA, PB; It is possible to declare two pointers to a character variable
Although:
Char *pa, *PB;
Also feasible, but relatively not in the form of TypeDef intuitive, especially in the need of a large number of pointers, the way typedef is more convenient.

Use two:
Used in the old C code (specific How old is not checked), to help the struct. In the previous code, when declaring a struct new object, you had to bring a struct with the form: struct struct name Object name, such as:
struct TAGPOINT1
{
int x;
int y;
};
struct tagPOINT1 p1;

In C + +, you can write directly: the name of the struct name object, which is:
TagPOINT1 P1;

It is too much trouble to think that someone often writes a struct, so they invent:
typedef struct TAGPOINT
{
int x;
int y;
}point;

Point P1; This is less than the original way to write a struct, more convenient, especially in the large use of time

Perhaps, in C + +, this use of TypeDef is not very large, but understanding of it, to master the old code is still helpful, after all, we may encounter in the project earlier legacy code.

Use three:
Use typedef to define platform-independent types.
For example, to define a floating-point type called REAL, on the target platform one, let it represent the highest precision type:
typedef long double REAL;
On platform two that does not support long double, replace the following:
typedef double REAL;
On three platforms that are not supported by double, replace the following:
typedef float REAL;
That is, when cross-platform, just change the typedef itself, do not make any changes to other source code.
This technique is widely used by the standard library, such as size_t.
In addition, because typedef defines a new alias for a type, it is not a simple string substitution, so it is more robust than a macro (although using macros can sometimes accomplish the above purposes).

Use four:
Define a new, simple alias for a complex claim. The method is: in the original declaration gradually replaced with the alias part of a complex declaration, so loop, the part with the variable name to the last substitution, get the original declaration of the most simplified version. Example:

1. Original declaration: Int * (*A[5]) (int, char*);
The variable name is a, and replacing a with a new alias Pfun is possible:
typedef int * (*PFUN) (int, char*);
The most streamlined version of the original statement:
Pfun A[5];

2. Original declaration: void (*b[10]) (void (*) ());
The variable name is B, replace the right part in parentheses, and Pfunparam as alias one:
typedef void (*pfunparam) ();
Replace the left variable B,pfunx with the alias two:
typedef void (*PFUNX) (Pfunparam);
The most streamlined version of the original statement:
Pfunx B[10];

3. Original declaration: Doube (*) () (*e) [9];
Variable named E, replace the left part first, Pfuny as alias one:
typedef double (*pfuny) ();
Replace the right variable E,pfunparamy with the alias two
typedef PFUNY (*pfunparamy) [9];
The most streamlined version of the original statement:
Pfunparamy e;

understand the "right-left" rule that is available for complex declarations: from the variable name, to the right, then to the left, the direction of the reading is reversed when the parentheses are analyzed, the parentheses are popped out of the brackets, or the left-to-right sequence is followed, until the entire declaration is parsed. Example:
Int (*func) (int *p);
First find the variable name func, there is a pair of parentheses outside, and the left is a * number, which means that func is a pointer, then jump out of this parenthesis, first look to the right, and also encounter parentheses, which means (*func) is a function, so func is a pointer to such a function, that is, a function pointer, Such functions have a formal parameter of type int*, and the return value type is int.
Int (*func[5]) (int *);
The right side of the Func is a [] operator, stating that Func is an array with 5 elements, and the left side of the Func has a *, stating that the element of Func is a pointer (note that this is not the modifier func, but the func[5], because [] operator precedence is higher than *, and Func is preceded by [] Combined). Jumping out of this parenthesis, looking to the right, and encountering parentheses, the element of the Func array is a pointer to the function type, which points to a function that has a int* type parameter and a return value of type int.

You can also remember 2 modes:
Type (*) (...) function pointers
Type (*) [] array pointer
---------------------------------

Trap One:
Remember, TypeDef is a new alias that defines a type, unlike macro, which is not a simple string substitution. Like what:
Define first:
typedef char* PSTR;
And then:
int mystrcmp (const PSTR, const PSTR);

is const PSTR actually equivalent to a const char*? No, it's actually equivalent to char* Const.
The reason is that const gives the entire pointer itself to be constant, that is, to form a constant pointer char* const.
Simply put, remember that when the const and typedef appear together, the typedef will not be a simple string substitution.

Trap Two:
A typedef is syntactically a keyword that stores a class (such as auto, extern, mutable, static, register, and so on), although it does not really affect the storage characteristics of an object, such as:
typedef static INT INT2; Not feasible
The compilation will fail with the hint "more than one storage class has been specified".

”】。 (Note that the TypeDef int* P[9] differs from typedef int (*P) [9], which defines an array that contains 9 int* type members, while the latter defines a pointer to an array, an array pointer, and the array that is pointed to contains 9 int type members.
It is easy to know them now, 工欲善其事, its prerequisite! Once we are familiar with this expression, we can use "typedef" to simplify this type of declaration.

Use of the C-language typedef (RPM)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.