Four purposes and two traps of typedef

Source: Internet
Author: User

Typedef is used to declare an alias. The syntax behind typedef is a declaration. I thought there would be no misunderstanding here, but the result was unexpected. There are not a few people who have misunderstandings. The culprit is the harmful teaching materials. When we introduce typedef in these textbooks, we usually write the following form: typedef int PARA; this form is almost the same as # define int PARA, as described in the previous chapters, these textbooks are designed from a simple perspective, but the actual behavior is partial. Indeed, this form is the simplest of all forms, but it does not further explain typedef, so many people use the # define thinking to look at typedef and separate int from PARA, int Is a part and PARA is another part, but in fact it is not the same thing. Int and PARA are a whole! Like int
I: Declaration is an overall declaration, except that int I defines a variable and typedef defines an alias.

Because of these incorrect ideas, these people cannot understand the following statements: typedef int a [10]; typedef void (* p) (void ); they will think that a [10] is the alias of int, (* p) (void) is the alias of void, but such alias does not seem to be a legal name, as a result, they are in confusion. In fact, the preceding statement declares a as the type alias of an array with 10 int elements. p is a type alias of a function pointer. Although typedef can be considered as an action to be separated from int PARA, in syntax, typedef is a storage class declaration specifier. Therefore, typedef is strictly
Int PARA is a complete statement. Define a function pointer type. For example, if the original function is void func (void), the defined function pointer type is typedef void (* Fun) (void). Then, a pointer to the function is generated using this type: Fun func1; after func1 obtains the function address, you can use the function pointer func1 (void) as you call the original function );

I. Purpose

Purpose 1:

Define a type of Alias, not just a simple macro replacement. It can be used as multiple objects that declare the pointer type at the same time. For example:

Char * pa, pb; // most of them do not conform to our intention. It only declares a pointer to a character variable,

// And a character variable;

The following are feasible:

Typedef char * PCHAR; // generally, uppercase is used.

PCHAR pa, pb; // feasible. Two pointers pointing to character variables are declared at the same time.

Although:

Char * pa, * pb;

It is also feasible, but it is not intuitive in the form of typedef, especially where a large number of pointers are required, the typedef method is more convenient.

Purpose 2:

It is used in the old C code (not checked for many old ones) to help struct. In the previous Code, when declaring a new struct object, you must carry the struct, that is, the form is: struct structure name object name, such:

Struct tagPOINT1

{

Int x;

Int y;

};

Struct tagPOINT1 p1;

In C ++, you can directly write: Structure name Object Name, namely:

TagPOINT1 p1;

It is estimated that it is too troublesome for someone to write another struct, so they invented:

Typedef struct tagPOINT

{

Int x;

Int y;

} POINT;

POINT p1; // in this way, a struct is written less than the original method, which is easier to use, especially when it is used in a large amount.

Maybe, in C ++, typedef is not very useful, but understanding it is helpful for mastering the old code, after all, we may encounter code that was left behind in earlier years in the project.

Purpose 3:

Use typedef to define platform-independent types.

For example, define a floating point type called REAL. On the target platform 1, make it the highest precision type:

Typedef long double REAL;

On Platform 2 that does not support long double, change:

Typedef double REAL;

On Platform 3 that is not supported by double, change:

Typedef float REAL;

That is to say, when using a cross-platform system, you only need to change the typedef itself, without any modifications to other source codes.

This technique is widely used in the standard library, such as size_t.

In addition, because typedef defines a new type of Alias, it is not a simple string replacement, so it is more robust than a macro (although it can do the above when a macro is used ).

Purpose 4:

Define a new simple alias for complex statements. The method is: gradually replace a part of the complex declaration with an alias in the original declaration. In this loop, leave the part with the variable name to the final replacement, and the most simplified version of the original declaration is obtained. Example:

1. Original Declaration: int * (* a [5]) (int, char *);

The variable name is a. replace a with a new alias pFun:

Typedef int * (* pFun) (int, char *);

The most simplified version of the original statement:

PFun a [5];

2. Original Declaration: void (* B [10]) (void (*)());

The variable name is B. Replace pFunParam with alias 1 in the brackets on the right:

Typedef void (* pFunParam )();

Replace B with the variable on the left, and pFunx with alias 2:

Typedef void (* pFunx) (pFunParam );

The most simplified version of the original statement:

PFunx B [10];

3. original statement: doube (*) (* e) [9];

The variable name is e. Replace the left part with pFuny as Alias 1:

Typedef double (* pFuny )();

Replace the variable e on the right, and pFunParamy is alias 2.

Typedef pFuny (* pFunParamy) [9];

The most simplified version of the original statement:

PFunParamy e;

Understand the "right-left rule" available for complex statements: Starting from the variable name, you must first go to the right and then to the left. When you encounter a parentheses, you can adjust the reading direction. After analyzing the parentheses, you can jump out of the brackets, it is still in the order of the first right and then the left, until the entire declaration analysis is complete. Example:

Int (* func) (int * p );

First, find the variable name func, and there is a pair of parentheses on the outside, and there is a * sign on the left, which indicates that func is a pointer. Then jump out of the parentheses and look at the right first, this indicates that (* func) is a function, so func is a pointer to this type of function, that is, a function pointer. This type of function has an int * type parameter, and the return value type is int.

Int (* func [5]) (int *);

The right side of func is a [] Operator, indicating that func is an array with five elements; there is a * on the left of func, indicating that the func element is a pointer (note that * is not a modifier of func, instead, modify func [5] Because the [] operator has a higher priority than *, and func is first combined ). Jump out of the brackets and look at the right side. The parentheses indicate that the element of the func array is a pointer of the function type. It points to an int * type parameter and the return value type is int.

You can also remember two modes:

Type (*)(....) Function pointer

Type (*) [] array pointer

-----------

Ii. traps

Trap 1:

Remember, typedef defines a new type of alias. Unlike macros, typedef is not a simple string replacement. For example:

First, define:

Typedef char * PSTR;

Then:

Int mystrcmp (const PSTR, const PSTR );

Is const PSTR actually equivalent to const char? No, it is actually equivalent to char * const.

The reason is that const gives the entire pointer itself constant, that is, the constant pointer char * const is formed.

Simply put, remember that when const and typedef appear together, typedef won't simply replace strings.

Trap 2:

Typedef syntax is a storage class keyword (such as auto, extern, mutable, static, register, etc.), although it does not really affect the storage features of objects, such:

Typedef static int INT2; // not feasible

Compilation will fail, and the system will prompt "more than one storage class is specified ".

 

Iii. Usage and difference of typedef and # define

1. Usage of typedef

In C/C ++, typedef is often used to define an alias for an identifier and a keyword. It is part of the language compilation process, but it does not actually allocate memory space, such:

Typedef int INT;

Typedef int ARRAY [10];

Typedef (int *) pINT;

Typedef enhances program readability and the flexibility of identifiers, but it also has disadvantages such as "non-intuitive.

2. # define usage

# Define is a macro definition statement. It is usually used to define constants (including non-parameters and parameters), and to implement macros that are "superficial and kind, long strings behind them, it is not carried out in the compilation process, but completed before (preprocessing), but it is difficult to find potential errors and other code maintenance problems, its instance is like:

# Define INT int

# Define TRUE 1

# Define Add (a, B) (a) + (B ));

# Define Loop_10 for (int I = 0; I <10; I ++)

In clause 1 of Scott Meyer's Objective C ++, we have analyzed the disadvantages of # define statements and good alternatives. For more information, see.

3. Differences between typedef and # define

From the above concepts, we can also understand that typedef is just a new name (only an alias) for the identifier to increase readability, and # define is originally used to define constants in C, the emergence of C ++, const, Enum, and inline has gradually become an alias tool. Sometimes it is easy to figure out which one should be used for typedef and which one should be used, for example, a statement such as # define int, which one can be used for the same purpose? I advocate the use of typedef, because in many early C compilers, this statement was invalid, but today's compiler has expanded. To be as compatible as possible, # define is generally followed to define "readable" constants and macro statement tasks, while typedef is often used to define keywords and lengthy type aliases.

Macro definition is just a simple string replacement (in-situ extension), while typedef is not in-situ extension, and its new name has a certain encapsulation, so that the new name identifier has a more convenient function to define variables. See the third line of the first code:

Typedef (int *) pint;

And the following line:

# Define pint2 int *

Same effect? Actually different! In practice, see the difference: pint a, B; has the same effect as int * A; int * B; indicates that two integer pointer variables are defined. Pint2 a, B; has the same effect as int * a, B; indicates defining an integer pointer variable A and an integer variable B.

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.