The C language is generated by the source code at the following stages:
C source program, compile-and-preprocessing, compile-and-build, assembler, linker, executable file
In the pre-compilation stage, the C source program is read, and the pseudo-instructions (the instructions beginning with #) and special symbols are processed. Or to scan the source code, the initial conversion to generate new source code to provide to the compiler. The preprocessing process precedes the compiler to process the source code.
In the C language, there is no intrinsic mechanism to do the following: include other source files at compile time, define macros, and, depending on the criteria, determine whether or not some code is included in the compilation. To do this, you need to use a preprocessor. Although the majority of compilers now contain preprocessor, they are generally considered to be independent of the compiler. The preprocessing process reads the source code, examines the statements and macro definitions that contain the preprocessing directives, and transforms the source code into a response. The preprocessing process also removes comments and extra white-space characters from the program.
Ii. definition of pseudo-directive (or preprocessing instruction)
A preprocessing directive is a line of code that begins with a # number. #号必须是该行除了任何空白字符外的第一个字符. #后是指令关键字, there are any number of whitespace characters allowed between the keyword and the # number. The entire line of statements forms a preprocessing directive that makes certain transformations to the source code before the compiler compiles it. The following is a partial preprocessing directive:
Instruction Use
# NULL instruction, no effect
#include contains a source code file
#define Defining macros
#undef to cancel a defined macro
#if If the given condition is true, compile the following code
#ifdef If the macro is already defined, compile the following code
#ifndef If the macro is not defined, compile the following code
#elif If the previous # if given condition is not true and the current condition is true, then compiling the following code is actually the shorthand for the else if
#endif End an # if ... #else条件编译块
#error Stop compiling and display an error message
Three, pre-processing directives mainly include the following four aspects:
1. Macro definition directive
A macro defines an identifier that represents a specific content. The preprocessing process replaces the macro identifier that appears in the source code with the value of the macro definition. The most common use of macros is to define a global symbol that represents a value. The second use of a macro is to define a macro with parameters (a macro function) that can be called like a function, but it expands the macro at the calling statement and replaces the formal parameter in the definition with the actual argument at the time of the call.
1.1 #define指令
1.1.1 #define预处理指令用来定义宏. The simplest form of the directive is to declare an identifier, giving the code that the identifier represents (such as a number like pi). In the following source code, we can use the defined macros instead of the code you want to use, for example:
Example 1
#define MAX_NUM 10
int Array[max_num];
In this case, for the person reading the program, the symbol Max_num has a specific meaning, which represents the maximum number of elements the array can hold. This value can be used more than once in a program. As a convention, it is customary to always use uppercase letters to define macros , which makes it easy to distinguish between macro identifiers and generic variable identifiers for programs. If you want to change the size of the array, you only need to change the macro definition and recompile the program.
1.1.2 The benefits of using macros are two points:
First, easy to use. As follows:
Example 2
#define PAI 3.1415926
Pai is obviously easier to write than 3.1415926.
The second is the definition of the macro has a meaning, readable. In the case of 1,max_num, the business of Wang Wen is known as the maximum number of meanings, more readable than the mere use of the 10 figure.
Three is easy to modify. As Example 1, if there are dozens of times in the program will be used to max_num, the modification only need to change in the macro definition once can, otherwise you will be modified to crash.
The value represented by the 1.1.3 macro can be a constant expression that allows the macro to be nested (which must be previously defined). For example:
Example 3
#define ONE 1
#define 2
#define SUM (One+two)
Here are two points to note:
One is to note that the above macro definition uses parentheses. Although they are not necessary. But in the light of caution, parentheses should be added. For example:
Six=three*two;
The preprocessing process converts the preceding line of code into:
six= (one+two) *two;
If there is no that parenthesis, it is converted into six=one+two*two;
That is, preprocessing is just a simple substitution of characters, so be aware of this and many errors will occur.
Second, although we use the example of the # define one 1, but generally require the macro definition to have its actual meaning, #define One 1 This meaningless macro definition is not recommended. (presumably that's what it means, forget how to say it specifically)
1.1.4 macros can also represent a string constant, for example:
#define VERSION "version 1.0 Copyright (c) 2003"
1.2 # define directive with parameters (macro function)
Macros and function calls with parameters look somewhat similar. See an example:
Example 4
#define CUBE (x) (x) * (x) * (x)
can be any numeric expression or even function call in place of the parameter x. Once again, you are reminded of the use of parentheses. Macro expansion is fully enclosed in parentheses, and the parameters are enclosed in parentheses, which guarantees the integrity of the macros and parameters. Look at a usage:
Example 4 usage
int num=8+2;
Volume=cube (num);
Expanded to (8+2) * (8+2) * (8+2);
Without those parentheses it becomes 8+2*8+2*8+2.
The following usage is not secure:
Volume=cube (num++);
If cube is a function, the above notation can be understood. However, because Cube is a macro, it can have side effects . The writing here is not a simple expression, they will produce unexpected results. They unfold after this:
Volume= (num++) * (num++) * (num++);
It is clear that the result is 10*11*12, not 10*10*10;
So how to use cube macro safely? You must move actions that may have side effects to the outside of the macro call :
int num=8+2;
Volume=cube (num);
num++;
Improper use of macro functions will cause some difficult to find errors, please use it carefully.
1.3 #运算符
The # operator that appears in the macro definition converts the argument followed by to a string. Sometimes the # of this usage is called the string operator. For example:
Example 5
#define PASTE (N) "adhfkj" #n
int main ()
{
printf ("%s\n", PASTE (15));
return 0;
}
Output Adhfj15
The # operator in the macro definition tells the preprocessor to convert any arguments in the source code that are passed to the macro into a string. So the output should be adhfkj15.
1.4 # #运算符 (rarely used)
# #运算符用于把参数连接到一起. The preprocessor appears in the # #两侧的参数合并成一个符号. Look at the following example:
Example 6
#define NUM (A,b,c) a# #b # #c
#define STR (A,b,c) a# #b # #c
int main ()
{
printf ("%d\n", NUM (+/-));
printf ("%s\n", STR ("AA", "BB", "CC"));
return 0;
}
The output of the final program is:
123
Aabbcc
2, conditional compilation instructions.
Programmers can decide which code the compiler will handle by defining different macros. Conditional compilation directives will determine which code is compiled and which is not compiled. You can determine the compilation criteria based on the value of the expression or whether a particular macro is defined.
2.1 #if/#endif/#else/#elif指令
#if指令检测跟在制造另关键字后的常量表达式. If the expression is true, compile the following code, knowing that #else, #elif或 #endif are present, otherwise it will not compile.
#endif用于终止 # if preprocessing directives.
After #else指令用于某个 the # if directive, the code that follows #else is compiled when the condition of the previous # if directive is not true.
Example 7
#define DEBUG //At this time #ifdef debug is True
#define DEBUG 0 //false at this time
int main ()
{
#ifdef DEBUG
printf ("debugging\n");
#else
printf ("Not debugging\n");
#endif
printf ("running\n");
return 0;
}
So that we can implement the debug function, each time to output debugging information, only need to #ifdef debug to determine once. No, it's not necessary. Defining a # define # DEBUG 0 at file start
#elif预处理指令综合了 the role of #else and # if directives.
Example 8
#define
int main ()
{
#ifdef One
printf ("1\n");
#elif defined
printf ("2\n");
#else
printf ("3\n");
#endif
}
2.2 #ifdef和 #ifndef
These are primarily used to prevent duplicate inclusions. We usually add such a paragraph in front of the. h header file:
Header files prevent duplicates from being included
FuncA.h
#ifndef funca_h
#define Funca_h
Header file Contents
#end If
This way, if A.H contains funca.h,b.h containing A.H, funcA.h, and duplicate inclusions, some type redefination errors will occur.
#if defined is equivalent to #ifdef; #if!defined equivalent to #ifndef
3, the header file contains instructions.
The main purpose of the header file is to make certain definitions available to a number of different C source programs. Because in a C source program that needs to use these definitions, you can simply add an # include statement instead of repeating the definitions in this file again. The precompiled program adds all the definitions in the head file to the output file it produces for processing by the compiler.
#include预处理指令的作用是在指令处展开被包含的文件. Inclusions can be multiple, meaning that a contained file can contain other files as well. The standard C compiler supports at least eight nested inclusions. The preprocessing process does not check whether a file is already contained in the conversion unit and prevents multiple inclusions for it, as described above.
There are two formats for including header files in your program:
#include <my.h>
#include "My.h"
The first method is to enclose the file with angle brackets. This format tells the preprocessor to search for included header files in the header files of the compiler's own or external libraries. The second method is to enclose the file in double quotation marks. This format tells the preprocessor to search for the included header file in the source code file of the currently compiled application, and then search the compiler's own header file if it is not found.
The rationale for using two different include formats is that the compiler is installed in a common subdirectory, and the compiled application is under their own private subdirectory. An application contains both the common header file provided by the compiler and the custom private header file. Two different inclusion formats allow the compiler to differentiate a common set of header files in many header files.
4, special symbols.
The precompiled program can recognize some special symbols. The precompiled program will replace the strings that appear in the source program with the appropriate values.
4.1 __line__
Note that it is a double underline, not a single underline. __FILE__ the string containing the current program file name __line__ the integer representing the current line number __date__ the string containing the current date __stdc__ if the compiler follows the ANSI C standard, it is a non-0 value __time__ String containing the current time
Example 9
#include <stdio.h>
int main ()
{
printf ("Hello world!\n");
printf ("%s\n", __file__);
printf ("%d\n", __line__);
return 0;
}
4.2 #line等
#error指令将使编译器显示一条错误信息, and then stop compiling.
#line指令改变_LINE_与_FILE_的内容, they are pre-defined identifiers in the compilation program.
#pragma指令没有正式的定义. The compiler can customize its purpose. A typical use is to prohibit or allow some annoying warning messages.
Example, #line举例
#line
#include <stdio.h> //Line No. 100
int main ()
{
printf ("Hello world!\n");
printf ("%d", __line__);
return 0;
}
Output 104
The pre-compiled program is basically the "substitution" of the source program. In this substitution, an output file with no macro definition, no conditional compilation instructions, and no special symbols is generated. The meaning of this file is the same as the source file without preprocessing, but the content is different. Next, the output file will be translated into machine instructions as the output of the compiler.
Preprocessing and compilation stages