1, Introduction to typedef
Four common uses of typedef:
1. Alias a defined variable type
2. Define function pointer type
3. Define array pointer type
4. Define a new simple alias for complex declarations
To sum up, "the type is the same with or without typedef". This sentence can be understood as follows:
If it is an array before typedef is added, then the array type is after typedef is added;
If it is a function pointer before adding typedef, then the function pointer type is after adding typedef;
If it is a pointer array before adding typedef, then after adding typedef, it is the pointer array type;
typedef char TA[5];//Define array type typedef char *TB[5];//Define the pointer array type. The variables defined by PA are arrays containing 5 char * pointer elements (pointer array type) typedef char *(TC[5]);//Pointer array type. Because [] has the highest binding priority, it makes no difference whether () is added or not. TC is equivalent to TB typedef char (*TD)[5];//Array pointer type
2, Detailed explanation of four uses of typedef
1. Alias a defined variable type
(1) typedef unsigned char uin8_t; //uint8_t is the alias of unsigned char, which is the most basic usage
(2) Structure usage - the function is to give struct _personan alias person_t, which is also very basic
struct __person { char name[20]; uint8_t age; uint8_t height; } typedef __person person_t; //The above two codes can also be combined into one paragraph, as follows: typedef struct __person { char name[20]; uint8_t age; uint8_t height; }person_t;
2. Define function pointer type
Let's first look at how to define function pointer variables, and then look at how to define function pointer types
(1) Define function pointer variables
int (*pFunc)(char *frame, int len);
A function pointer variable pffunc is defined, which can point to such a function: the return value is int, and the formal parameters are char *, int
int *(*pFunc[5])(int len);
Five function pointer variables are defined: pffunc [0], pffunc [1] ··. They can all point to such a function: the return value is int *, and the formal parameter is int
(2) Define function pointer type
Typedef must be used to define the function pointer type. The method is to add typedef to "define function pointer variable".
typedef int (*pFunc_t)(char *frame, int len); / / defines a type pFunc_t
give an example:
typedef int (*pFunc_t)(char *frame, int len);//A type pffunc_t is defined int read_voltage(char *data, int len) { int voltage = 0; ···//Other function codes return voltage; } int main(void) { pFunc_t pHandler = read_voltage;//Use the type pffunc_t to define a function pointer variable ···//Other function codes }
3. Define array pointer type
This problem is still divided into two steps. First, see how to define array pointer variables, and then see how to define array pointer types
(1) Define array pointer variables
① int(*pArr)[5]; / / defines an array pointer variable pArr, which can point to a one-dimensional array of int [5]
② char(*pArr)[4][5]; / / / defines an array pointer variable pArr, which can point to a two-dimensional array of char[4][5]
int(*pArr)[5];//pArr is a pointer variable to a one-dimensional array containing five int elements int a[5] = {1,2,3,4,5}; int b[6] = {1,2,3,4,5,6}; pArr = &a;//Completely legal, no warning pArr = a;//Compilation warning occurred, type mismatch during assignment: a is of type int(*) and pArr is of type int(*)[5] pArr = &a[0];//Compilation warning occurred, type mismatch during assignment: a is of type int(*) and pArr is of type int(*)[5] pArr = &b;//Compilation warning occurred, type mismatch during assignment: & B is of type int(*)[6], while pArr is of type int(*)[5] pArr = (int(*)[5])&b;//Cast type to int(*)[5], completely legal, no warning
In the above example, when using type conversion, the code style is slightly complex. Imagine, if we forcibly convert it to a pointer to a structure array, how long is the content in the forcibly converted bracket! This directly affects the readability of the code. Therefore, the forcibly converted class should be defined
(2) Define array pointer type
Just like the method of defining the function pointer type above, you can directly add typedef in front, for example
typedef int (*pArr_t)[5]; / / defines a pointer type pArr_t, which can point to an array containing 5 int elements
typedef int(*pArr_t)[5];//Define a pointer type that can point to a one-dimensional array with 5 int elements int main(void) { int a[5] = {1,2,3,4,5}; int b[6] = {1,2,3,4,5,6}; pArr_t pA;//Define array pointer variable pA pA= &a;//Completely legal, no warning pA= (pArr_t)&b;//Cast type to pArr_t, completely legal, no warning }
(2) Define array type
If we want to declare a one-dimensional array with 5 int elements, it is generally written as follows: int a[5];
If we want to declare multiple one-dimensional arrays with five int elements, it is generally written as int a1[5], a2[5], a3[5] ·, or a[N][5]
It can be seen that defining multiple one-dimensional arrays is slightly complex. At this time, we should define the array as a type, for example:
typedef int arr_t[5]; / / defines an array type arr_t, and the variable of this type is an array
typedef int arr_t[5]; int main(void) { arr_t d; //D is an array, and this line is equivalent to: int d[5]; arr_t b1, b2, b3;//B1, B2 and B3 are arrays d[0] = 1; d[1] = 2; d[4] = 134; d[5] = 253;//Compilation warning: subscript out of bounds }
4. Define a new simple alias for complex declarations
Define a new simple alias for a complex declaration. The method is to gradually replace a part of the complex declaration with an alias in the original declaration. In this cycle, leave the part with variable name for the last replacement to obtain the most simplified version of the original declaration. For example:
int *(*a[5])(int, char*);//Original declaration typedef int *(*pFun)(int, char*); //The variable name is a. just replace a with a new alias pFun pFun a[5];//The most simplified version of the original statement
void (*b[10]) (void (*)());//Original declaration typedef void (*pFunParam)();//The variable name is b, replace the one in the bracket on the right, and pfumparam is the alias one typedef void (*pFunx)(pFunParam);//Then replace the variable b on the left and pFunx as alias 2 pFunx b[10];//The most simplified version of the original statement
3, Two traps
Trap 1: remember, typedef is a new alias that defines a type. Unlike macros, it is not a simple string replacement.
Trap 2: typedef is syntactically a keyword of a storage class (such as auto, extern, mutable, static, register, etc.), although it does not really affect the storage characteristics of objects.
4, The difference between typedef and #define
Case 1:
Generally speaking, typedef is better than #define, especially when there are pointers. Please see an example:
typedef char *pStr1; #define pStr2 char *; pStr1 s1, s2; pStr2 s3, s4;
In the above variable definitions, s1, s2 and s3 are defined as char *, while s4 is defined as char, which is not the expected pointer variable. The fundamental reason is that #define is just a simple string replacement, while typedef is a new name for a type.
Case 2:
The compiler will report an error in the following code. Do you know which statement is wrong?
typedef char * pStr; char string[4] = "abc"; const char *p1 = string; const pStr p2 = string; p1++; p2++;
p2 + + is wrong. This problem reminds us once again that typedef is different from #define. It is not a simple text replacement. const pStr p2 in the above code is not equal to const char * p2. const pStr p2 and const long x are essentially the same. They are read-only restrictions on variables, but the data type of variable p2 here is defined by ourselves rather than the inherent type of the system Therefore, const pStr p2 means: * the variable p2 whose data type is char is restricted to be read-only, so p2 + + error.
reference material:
https://blog.csdn.net/qq_31073871/article/details/81258558
https://blog.csdn.net/superhoy/article/details/53504472
C Primer Plus (Sixth Edition) Chinese version
C and pointer