Usage of typedef (III)

Source: Internet
Author: User

1. Basic explanation

Typedef is a key word in C language. It defines a new name for a data type. The data types here include internal data types (INT, Char, etc.) and Custom Data Types (struct, etc ).

In programming, typedef is generally used for two purposes. One is to give a variable a new name that is easy to remember and clear, and the other is to simplify some complicated type declarations.

As for the subtlety of typedef, let's take a look at the specifics of several problems.

2. typedef & Structure Problems

When the following code defines a structure, the compiler reports an error. Why? Does the C language not allow the structure to contain pointers to itself? First, let's look at the following description:
Typedef struct tagnode
{
Char * pitem;
Pnode pnext;
} * Pnode;

Answer and analysis:

1. The simplest use of typedef
Typedef long byte_4;

Give a new name for the known data type long, called byte_4.

2. Use typedef in combination with the structure
Typedef struct tagmystruct
{
Int inum;
Long llength;
} Mystruct;

This statement actually completes two operations:

1) define a new structure type
Struct tagmystruct
{
Int inum;
Long llength;
};

Analysis: tagmystruct is called "tag", that is, "tag". It is actually a temporary name. The struct keyword and tagmystruct constitute this structure type, whether or not there is typedef, this structure exists.

We can use struct tagmystruct varname to define variables, but note that it is incorrect to use tagmystruct varname to define variables, Because struct and tagmystruct can be combined to represent a structure type.

2) typedef is named mystruct for the new structure.
Typedef struct tagmystruct mystruct;

Therefore, mystruct is actually equivalent to struct tagmystruct. We can use mystruct varname to define variables.

Answer and Analysis

C language certainly allows a pointer to its own in the structure. We can see countless such examples in the implementation of data structures such as the establishment of a linked list. The fundamental problem of the above Code lies in the application of typedef.

According to the above description, we can know that the pnext domain declaration is encountered during the creation of the new structure. The type is pnode. You must know that pnode represents the new name of the type, when the type itself is not created, the new name of the type does not exist. That is to say, the compiler does not know pnode at this time.

There are many ways to solve this problem:

1 ),
Typedef struct tagnode
{
Char * pitem;
Struct tagnode * pnext;
} * Pnode;

2 ),
Typedef struct tagnode * pnode;
Struct tagnode
{
Char * pitem;
Pnode pnext;
};

Note: In this example, you use typedef to give a new name for a type that is not fully declared. C language compiler supports this approach.

3) standard practices:
Struct tagnode
{
Char * pitem;
Struct tagnode * pnext;
};
Typedef struct tagnode * pnode;

3. typedef & # define

There are two methods to define the pstr data type. What are the differences between the two? Which one is better?
Typedef char * pstr;
# Define pstr char *;

Answer and analysis:

Generally, typedef is better than # define, especially when there is a pointer. See the example below:
Typedef char * pstr1;
# Define pstr2 char *;
Pstr1 S1, S2;
Pstr2 S3, S4;

In the preceding variable definition, S1, S2, and S3 are both defined as char *, while S4 is defined as char, which is not the expected pointer variable, the root cause is that # define is a simple string replacement, while typedef is a new name for a type.

# Define usage example:
# Define f (x) x * x
Main ()
{
Int A = 6, B = 2, C;
C = f (a)/F (B );
Printf ("% d", C );
}

The output result of the following program is: 36.

For this reason, when # define definition is used in many C language programming specifications, if the definition contains expressions and must use parentheses, the above definition should be as follows:
# Define f (x) (x * X)

Of course, if you use typedef, there is no such problem.

4. Another example of typedef & # define

In the following code, the compiler reports an error. Do you know which statement is wrong?
Typedef char * pstr;
Char string [4] = "ABC ";
Const char * P1 = string;
Const pstr P2 = string;
P1 ++;
P2 ++;

Answer and analysis:

P2 ++ error. Another reminder is that typedef is different from # define, which is not a simple text replacement. In the above Code, const pstr P2 is not equal to const char * P2. There is no difference between const pstr P2 and const long x in nature. They both impose read-only restrictions on variables, except that the data type of the variable P2 is defined by ourselves rather than the inherent type of the system. Therefore, const pstr P2 indicates that the variable P2 with the Data Type limited to char * is read-only, so P2 ++ is incorrect.

# Define and typedef Extension

1) # define macro definition has a special advantage: You can use # ifdef, # ifndef, and so on for logical judgment. You can also use # UNDEF to cancel definition.

2) typedef also has a special advantage: It complies with range rules, the type of a variable defined by typedef is restricted to the defined function or file (depending on the location of the variable definition), while the macro definition does not.

5. typedef & Complex Variable Declaration

In programming practices, especially when looking at other people's code, we often encounter complicated variable declarations and use typedef to simplify our own values, such:

The following is the declaration of three variables. I want to use typdef to define an alias for them. What should I do?
> 1: int * (* A [5]) (INT, char *);
> 2: void (* B [10]) (void (*)());
> 3. Doube (*) (* pA) [9];

Answer and analysis:

The method to create a type alias for a complex variable is very simple. You only need to replace the variable name with the type name in the traditional variable declaration expression, and then add the keyword typedef to the beginning of the statement.
> 1: int * (* A [5]) (INT, char *);
// Pfun is a type alias we created
Typedef int * (* pfun) (INT, char *);
// Declare an object using the new defined type, equivalent to int * (* A [5]) (INT, char *);
Pfun A [5];

> 2: void (* B [10]) (void (*)());
// First declare a new type for the blue part of the above expression
Typedef void (* pfunparam )();
// Declare a new type as a whole
Typedef void (* pfun) (pfunparam );
// Declare the object using the new defined type, which is equivalent to void (* B [10]) (void (*)());
Pfun B [10];

> 3. Doube (*) (* pA) [9];
// First declare a new type for the blue part of the above expression
Typedef double (* pfun )();
// Declare a new type as a whole
Typedef pfun (* pfunparam) [9];
// Declare an object using the new defined type, equivalent to Doube (*) (* pA) [9];
Pfunparam Pa;

 

The following three documents are summarized in learning typedef:
// Article 1st: typedef statement format
# Include <stdio. h>
Typedef int gtype; // defines the global type gtype.
Void main ()
{
// 1. Basic Format
Typedef char ch; // redefines the basic type
Typedef struct {int A, B, C;} stru; // redefinition of the custom type (structure, sharing, enumeration)
Typedef Union {int A, B, C;} Unio;
Typedef Enum {One, Two, Three} num;
Typedef char * STR; // redefine the derived type (pointer, array, function)
Typedef int Ai [10];
Typedef void fun (void );
// Visible, the format used by typedef is: typedef variable/Function Definition Statement, that is, adding at the beginning of the original variable/Function Definition Statement
// Typedef, you can rewrite the original variable/Function Definition Statement to the Type Definition Statement. The original variable name/function name is the type name.
// Note: when the basic and custom types are redefined, the format can also be summarized as: typedef Original Type New Type 1, new type 2 ,...;

// 2. Observe the original type
// 1. The original type can have a type qualifier
Typedef const int ci; // the original type contains the const qualifier
CI = 3;
// CI = 4; // The visible CI does represent the const int

// 2. The original type can be a new type defined by typedef
Typedef ch newch; // ch is previously defined as char
Newch NC = 'a ';

// 3. The original type cannot contain a storage class
// Typedef static int Si; // error, "more than one storage class is specified"
// Typedef register int Ri; // error same as above

// 4. The original type should be a type, not a variable/Object
Float f = 0; // define F as a variable
// Typedef f fl; // Error

// 5. The type cannot be redefined.
Typedef const con; // redefine const
// Con int A = 0; // but this type cannot be used normally
Typedef unsigned us; // redefine unsigned
US US1 = 0; // correct, equivalent to unsigned int
// Us int us2; // error, cannot be used normally
// Note: Since const and unsigned are not independent types, it is inconvenient to redefine them.

// 3. Observe the New Type
// 1. Scope of the New Type
Typedef int ltype; // defines the local type ltype
Void fun (); // check whether ltype is valid in fun
Fun ();
// It can be seen that the types defined by typedef also have scopes. In a function, typedef is used to define a local type.
// Typedef can also be placed out of the function like a variable definition statement. In this case, the global type is defined.

// 2. Can the new type be an existing type?
// Typedef int float; // error. The standard type cannot be redefined.
Typedef int type; // defines the new type.
// Typedef char type; // error, "type redefinition"
Typedef int gtype; // correct. Although gtype is an existing type, it is defined outside of this function.
// Visible, the new type name must be a valid identifier and must be unique within its scope

// 3. Can there be more than one new type?
Typedef float length, width; // two aliases for float, length and width
Length L = 0; // define a variable with a New Type
Width W = 0;
// Visible. Multiple aliases can be specified for an original type at a time.

// 4. Can multiple different types be defined at a time?
// Typedef int I, float F; // two different types of I and F are defined at a time.
// F v = 6.0; // try to use the F type
// Printf ("V = % F", V); // v = 0, type F is invalid
// Visible, A typedef statement should only define an alias for an original type

}
Void fun ()
{// Ltype I; // error, "ltype: Undefined identifier"
Gtype G = 1; // use the global type gtype
Printf ("G = % d", g); // normal use
}

// Article 1: typedef Specific Application

# Include <stdio. h>
Int fun1 (int A, int B) {return 0 ;}
Int fun2 (int A, int B) {return 0 ;}
Int fun3 (int A, int B) {return 0 ;}
Void main ()
{// 1. advantages of using typedef
// 1 You can get a more meaningful name for the existing type to increase the readability of the program, as shown in
Typedef char * string;
String S1 = "string1", S2 = "string2"; // string can be used as a string

// 2 make the variable definition shorter and reduce the trouble of writing, such
Typedef float A3 [2] [3] [4]; // get the brief name A3 for a 2*3*4 real Array
A3 A, B, C; // equivalent to defining float a [2] [3] [4], B [2] [3] [4], c [2] [3] [4]
Typedef unsigned int (* pfun) (INT (*) [4]); // pfun is a function pointer. This function parameter is a one-dimensional array pointer and the return value is an unsigned integer.
Pfun pf1, pf2; // equivalent to defining unsigned int (* pf1) (INT (*) [4]); unsigned int (* pf2) (INT (*) [4])

// 3 before defining complex types, use typedef to create some intermediate types, and then use the intermediate types to construct complex types to reduce their complexity (main purpose)
// Example: complex definition
INT (* AP [3]) (INT, INT); // AP is an array whose element is a function pointer. The parameters and return values of this type of function are both integer.
// Use typedef to reduce definition difficulty
// Method 1
Typedef int (* PF) (INT, INT); // define pf as the pointer to this function
PF AP1 [3]; // AP1 is an array. Each element is of the PF type.
AP1 [0] = fun1; AP1 [1] = fun2; AP1 [2] = fun3;
// Method 2
Typedef int fun (INT, INT); // define this function as fun type
Fun * AP2 [3]; // AP2 is an array. Each element is a pointer to fun.
AP2 [0] = fun1; AP2 [1] = fun2; AP2 [2] = fun3;

// 4 Increase Program portability (facilitating program transplantation between different processors, operating systems, and compiling systems)
/* For example, the program segment for reading files under TC is as follows:
File * FP;
Long buffer1;
Fread (& buffer1, sizeof (long), 1, FP); // read 4 bytes each time
If you need to read 8 bytes at a time under VC, the program needs to be modified as follows:
Double buffer2;
Fread (& buffer2, sizeof (double), 1, FP );
The typedef method is used. The program section is as follows:
Typedef long unit; // Unit indicates long in TC and double in VC.
Unit buffer;
Fread (& buffer, sizeof (unit), 1, FP); // read unit bytes each time
When porting to VC, you only need to change the definition of unit: typedef double unit ;*/

// II. Differences between typedef and define
// Define can also be used to replace simple types, as shown in figure
# Define int long // replace long with int
// The differences between the two methods are as follows:
// 1. The processing time is different between the two. Macro replacement is performed during pre-compilation, while the type definition is processed during formal compilation.
// 2 the two are essentially different. Macro replacement simply replaces the macro name with the target string, and the type definition is the same as the definition variable.
// It actually adds an available type for the program
// 3. The complexity is different. You can use typedef to define various complex types and use new types in various ways (see 10_10_2.cpp for details)
// While define can only replace the basic and custom types, it cannot replace the derived type, and it is not safe to use, such
# Define PI int * // try to replace integer pointer with pi
Pi PI1; // correct. After expansion, it is int * PI1;
Pi Pi2, PI3; // error. The original intention is to define both Pi2 and PI3 as integer pointers, but after expansion, it is int * Pi2, PI3; PI3 is not defined as a pointer.

# Define num Enum {One, Two, Three} // try to replace the enumeration type with num
Num N1; // The enumerated constants one, two, three, and N1 are defined.
// Num N2; // error. After expansion, it is Enum {One, Two, Three} N2. This leads to redefinition of the enumerated constants one, two, and three.

# Define date struct {int y, M, D ;}
Date * PD; // The structure pointer is defined correctly.
// Pd = (date) 1; // error. After expansion, it is Pi = (struct {int y, M, D;}) 1. Currently, conversion of this type is not supported.

# Define time Union {int H, M, s ;}
// Int L = sizeof (time); // error. Int L = sizeof (Union {int H, M, s;}) after expansion; sizeof operand Error
// It can be seen that unexpected errors may occur when you replace the type with define, so avoid using it instead of using a safe typedef.

}

 

// Article 2nd: detailed use of typedef/* in order to make it easy to use typedef, the C ++ data type is reclassified by type name source and complexity as follows: i. Basic type (the type name is a single identifier specified by the System) in, Char, float, double, void, const II. Custom type (the type name is a single identifier defined by the user) 1. structure Type: struct stru {int I; struct stru * ;}; 2. union Unio {int I; Enum [10] ;}; 3. enum {a, B, c}; 4. typedef type typedef double dB; 3. derived type (the type name is composed of an existing type and other symbols) 1. pointer type (composed of existing types *) void *, char **, void (*) (), struct stru *, Enum * 2. array type (composed of [] []) int [3] [4], struct stru [10 ], Enum [10], char * [10] 3. function Type (type name is a function prototype composed of various symbols) void main (void), char * strcpy (char *, char *) above three categories of Type identifiers from simple to complex, when learning typedef, you need to follow the sequence, practice each type of redefinition, define a new type, and then use it from the following aspects: use it to define variables, pointers, arrays, objects with storage classes, and objects with const; use it for function parameters and return value types; use it for type conversion; use sizeof to calculate the length */# include <stdio. h> # include <stdlib. h> void main () {// 1. Redefine the basic type // 1. define typedef int in; typedef char ch; typedef float FL; typedef double dB; typedef unsigned int UI; // or write it as typedef UN Signed UI; typedef unsigned char UC; typedef void VO; // 2. use in I = 3; printf ("I = % d", I); // use the new type to define the variable Ch * Pc = "PC "; printf ("PC = % s", PC); // define the pointer fl af [3] = {1, 2, 3} with the new type }; printf ("AF [0] = % F", AF [0]); // define the array static double SD with the new type; printf ("SD = % F ", SD); // use the new type to define the const UI Cui = 3; printf ("Cui = % d", Cui ); // use the new type to define the variables VO fun1 (UC); fun1 ('A') with the type qualifier '); // use the new type as the function parameter and return value type printf ("in (1.5) = % d", in (1.5 )); // use the new type as the type conversion printf ("$ db = % d", Si Zeof (db); // evaluate the length of the new type, $ db = $ double = 8 // 2. Redefine the custom type // 1. define // (1) Complete syntax (define the custom type first and then redefine it) struct datetype // redefine the structure type {UI year; // The UI is the unsigned int; UC month; // UC is the unsigned char; UC day ;}; typedef datetype date; Union scoretype // redefines the sharing type {FL sco1; Ch * sco2 ;}; typedef scoretype score; Enum numtype {One, Two, Three}; // redefinition of the enumeration type typedef numtype num; typedef num newnum; // redefinition of the typedef type // (2) common syntax (for structure, sharing, and enumeration definition statements without a type name, it is directly duplicated Definition) typedef struct {UC Hou, Min, SEC;} time; typedef Union {FL sco1; Ch * sco2 ;}sco; typedef Enum {red, green, blue} color; // visible, regardless of the Writing Method, follow the format of the typedef statement: New Type of the original typedef type; // 2. use date Vs = {, 15}; // define the structure variable printf ("vs: % d. % d. % d ",. year,. month,. day); score vu, * Pu = & VU; printf ("& vu = % x Pu = % x", & vu, Pu ); // define the shared pointer newnum AE [3] = {One, Two, Three }; // define the enumeration array printf ("AE [0] = % d AE [1] = % d AE [2] = % d", AE [0], AE [1], AE [2]); stati C num VN; // defines the printf ("VN = % d", vn); const SCO cs = {90 }; // define the const object printf ("Cs. sco1 = % F ", CS. sco1); time fun2 (time); // function parameters and return value types static time vt = fun2 (VT); printf ("fun2: % d: % d ", VT. hou, VT. min, VT. sec); VN = (Num) 10; printf ("VN = % d", vn); // use the new type as the type conversion printf ("$ time = % d ", sizeof (time); // evaluate the length of the new type, $ time = 3 printf ("$ SCO = % d", sizeof (SCO )); // evaluate the length of the new type, $ SCO = 4 printf ("$ color = % d", sizeof (color); // evaluate the length of the new type, $ color = 4 // unfinished To be continued // 2. redefines the array type // (1) defines typedef int Ai [5]; // redefines the basic type array typedef float A2 [3] [4]; // redefines the array type array (two-dimensional array) typedef time as [2]; // redefines the structure type array typedef SCO au [2]; // redefinition of the shared array typedef color ae2 [2]; // redefinition of the enumerated array typedef char * AP2 [2]; // redefinition of the pointer array // note: when the array is redefined, C ++ does not currently support regular expressions like typedef int [10] AI // (2) using // defining variables (array variables) AI vai = {1, 2, 3, 4, 5}; // equivalent to int vai [5]; printf ("vai: % d", vai [0], vai [1]); // define the pointer (array pointer) A2 va2, * pa2 = & va2; // equivalent to float va2 [3] [4 ], (* Pa2) [3] [4] = & va2; printf ("& va2 = % x pa2 = % x", va2, pa2 ); // define an array (multi-dimensional array) as vas [2] ={{ 10, 20, 30 },{ 20, 40, 59 }}; // VAS is a two-dimensional structure array, equivalent to time vas [2] [2]; printf ("VAS [0] [0]: % d", vas [0] [0]. hou, vas [0] [0]. min, vas [0] [0]. sec); // defines the static au Vau array with storage class; // Vau is a static shared array printf ("Vau [2]: % F ", VAU [0]. sco1, Vau [1]. sco1); // defines the cosnt array const ae2 cae2 = {red, green}; // cae2 is a constant enumeration array printf ("cae2 [2]: % d ", cae2 [0], cae2 [1]); // Define the function void fun4 (AP2); // The parameter is a pointer array, equivalent to void fun4 (char * AP2 [2]); AP2 vap2 = {"str1 ", "str2"}; // the two elements of vap2 point to "str1" and "str2" fun4 (vap2); printf ("$ AI = % d ", sizeof (AI); // evaluate the length of the new type, $ AI = $ int [5] = 20 printf ("$ A2 = % d", sizeof (A2 )); // evaluate the length of the new type, $ A2 = $ float [3] [4] = 48 printf ("$ as = % d", sizeof ()); // evaluate the length of the new type, $ as =$ = time [2] = 6 printf ("$ Au = % d", sizeof (Au )); // evaluate the length of the new type, $ au =$ = SCO [2] = 8 printf ("$ ae2 = % d", sizeof (ae2 )); // evaluate the length of the new type, $ ae2 = $ color [2] = 8 Printf ("$ AP2 = % d", sizeof (AP2); // evaluate the length of the new type, $ AP2 =$ = char * [2] = 8 // note: because the function return value cannot be of the array type, the redefinition type is no longer used as the function return value type. // 3. redefinition of the function type // (1) definition method int fun (INT, INT); // declares a function, it has two Integer Parameters and the return value is an integer typedef int fun (INT, INT); // defines a type, it represents a function that contains two Integer Parameters and returns an integer. // (2) usage // defines the variable (function) fun Max, min; // two objects, Max and Min, are defined with type fun. Since fun is a function type, they are naturally function objects. // This is equivalent to int max (INT, INT) and int min (INT, INT) Declare printf ("max () = % d", max )); // call the two functions printf ("min (3, 5) = % d ", Min (3, 5); // defines the pointer (function pointer) Fun * pfun; // pfun is a pointer that specifically points to fun objects. It is equivalent to defining int (* pfun) (INT, INT); pfun = max; // both Max and min are fun objects printf ("& max = % x pfun = % x", Max, pfun); // other objects are meaningless, // visible. If many functions with the same type but different names need to be used in the program, you can use typedef to abstract the type and then use this type. // you can declare many functions at a time, to simplify the writing of the function prototype. However, this type can only be used to declare functions, but not to define functions} // main end // The following is the void fun1 (unsigned char p) function used in main) // because the vo and UC scopes are not here, void and unsigned {printf ("fun1: % C", P) are directly used here ); // In this way, the function prototype VO fun1 (UC) corresponds to} typedef struct {unsigned char Hou, Min, SEC;} time; // because the scope of the time type in main has ended, therefore, time fun2 (time p) {P must be redefined here. hou = 20; p. min = 30, p. SEC = 55; return P;}/* Note: strictly speaking, the time here is not of the same type as the time in the main function prototype, however, the system ignores this correct usage. Time in main should be defined at the beginning of the program as a global type, so that subsequent functions can share this type */void * F Un3 (float ** p) {printf ("fun3: malloc (% d)", P); Return malloc (INT (p ));} typedef char * AP2 [2]; void fun4 (AP2 p) {printf ("fun4: P [0] = % s p [1] = % s ", P [0], p [1]);} int max (int A, int B) {return A> B? A: B;} int min (int A, int B) {return a <B? A: 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.