Pre-processing commands and naming existing types with typedef, pre-processing typedef
Preprocessing command
It is mainly to improve the programming environment to improve programming efficiency. It is not part of the C language itself and cannot be compiled directly. It must be completed before compiling the program, perform "preprocessing" on these special commands in the program first ". For example, header files.
There are three types: macro definition, file inclusion, and Conditional compilation.
Macro definition (two types are available: with and without parameters)
The macro definition replaces a string with the macro name, which is also a simple replacement and does not check the correctness.
The macro definition is not a C statement and does not have to add points in the row;
# The define command appears outside the function in the program. The limited scope of the macro name is to define the command and end with the source file.
You can use the # undef command to terminate the macro-defined scope.
Do not replace the characters in the string enclosed by double apostrophes in the program.
The macro definition is different from the definition variable. It is only replaced by characters and no space is allocated;
Macro definition with parameters (not only simple string replacement, but also parameter replacement)
The macro definition with parameters is different from the function definition, mainly including the following:
When calling a function, first obtain the value of the real parameter expression, and then bring it into the form parameter. Macros only replace simple characters.
Function calls are processed when the program is running, and temporary memory units are allocated for the parameters. Macro expansion is performed before compilation. During expansion, memory units are not allocated, values are not transferred, and the concept of "return value" is not involved.
You must define the type for both the real parameters and the form parameters in the function. The two parameters must be consistent. The macro does not have a type problem, and the macro name does not have a type. When a macro is defined, a string can be any type of data.
You can call a function to obtain only one returned value, but use a macro definition to obtain several results.
When macros are used for a large number of times, the source code becomes longer after macros are expanded, but function calls do not.
Macro replacement does not take up the running time, but only the Compilation Time. Function calls occupy the running time (memory allocation, field reservation, and return value)
File Inclusion
The so-called "File Inclusion" processing means that one source file can include all the content of another source file, that is, other files are included in this file. (# Include ...)
In addition to function prototype and macro definition, header files can also include struct type definition and global variable definition.
Conditional compilation
A part of the program must be compiled only when certain conditions are met, that is, the compilation conditions are specified for this part of content. This is Conditional compilation.
Conditional compilation has the following forms:
#ifdef identifier
Network 1
#else
Block 2
#endif
#if expression
Network 1
#else
Block 2
#endif
// conditional compilation
#include <stdio.h>
#define LETTER 1
void main ()
{
char str [20] = "C Language", c;
int i = 0;
while ((c = str [i]! = '\ 0'))
{
i ++;
#if LETTER
if (c> = 'a' && c <= 'z')
c = c-32;
#else
if (c> = 'A' && c <= 'Z')
c = c + 32;
#endif
printf ("% c", c);
}
printf ("\ n");
}
Use typedef to name existing types
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 ".
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 int, which one can be used for the same purpose? The idea is to use typedef, because in many early C compilers, this statement was invalid, but the current 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.
1. First, the execution time of the two is different.
The keyword typedef is valid in the compilation phase. Because it is in the compilation phase, typedef has the type check function.
Define is a macro definition, which occurs in the preprocessing phase, that is, before compilation. It only performs simple and mechanical string replacement without any check.
# Define usage example:
#define f(x) x*x
main( )
{
int a=6,b=2,c;
c=f(a) / f(b);
printf("%d \n",c);
}
The output result of the program is: 36. The root cause is that # define is a simple string replacement, and should be enclosed in brackets "(X * X )".
2. Different Functions
Typedef is used to define the type alias. These types include not only internal types (int, char, etc.), but also custom types (such as struct), which can be used to make the type easy to remember.
For example:
- Typedef int (* PF) (const char *, const char *);
Define the Data Type PF of a pointer to a function. The return value of the function is int and the parameter is const char *.
Another important purpose of typedef is to define machine-independent types. For example, you can define a floating point type called REAL. On the target machine, it can obtain the highest precision:
- 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;
# Define can not only take aliases for types, but also define constants, variables, and compilation switches.
3. different scopes
# Define has no scope restrictions. As long as it is a previously predefined macro, it can be used in future programs. Typedef has its own scope.
-
void fun ()
{
#define A int
}
void gun ()
{
// A can also be used here, because macro replacement has no scope,
// But if typedef is used above, then A cannot be used here, but generally typedef is not used in functions
}
4. pointer operations
They have different functions when modifying the pointer type.
-
Typedef int * pint;
#define PINT int *
Const pint p; // p can not be changed, the content pointed to by p can be changed, which is equivalent to int * const p;
Const PINT p; // p can be changed, and the content pointed to by p cannot be changed, which is equivalent to const int * p; or int const * p;
pint s1, s2; // s1 and s2 are both int pointers
PINT s3, s4; // equivalent to int * s3, s4; only one is a pointer
In fact, the labels at the end of typedef and define are also different. I hope you will not ignore this. Through the analysis in this article, I believe you have understood the difference between the two. After understanding the difference, it will be more flexible to use.