C language learning record (fifteen) C preprocessor and C library

1. C preprocessor

The C preprocessor looks at the program before it is executed (hence the name preprocessor). According to the preprocessing instructions in the program, the preprocessing replaces the symbol abbreviation with other content.

1.1 Translation procedure

Before preprocessing, the compiler must do some translation processing on the program. First, the compiler maps the characters that appear in the source code to the source character set. This processing handles multibyte and three-character sequences.

Second, the compiler locates every instance of a backslash followed by a newline, and removes them.

Third, the compiler divides the text into sequences of preprocessing tokens, whitespace, and comments (tokens are items separated by spaces, tabs, or newlines). The compiler will replace each comment with a space character.

1.2 Explicit constants: #define

The #define preprocessing directive, like other preprocessing directives, begins a line with the # sign. Both ANSI and later standards allow spaces or tabs before the # sign, and also allow spaces between the # and the rest of the directive. However, older versions of C require that directives start at the far left of a line, and that # and the rest of the directive must not have spaces. Directives can appear anywhere in a source file. Its definition is valid from the point where the directive appears to the end of the file. We make heavy use of the #define directive to define explicit constants (also called symbolic constants). But the directive has other uses as well. The following example illustrates.

#include <stdio.h>

#define TWO 2   /* 可以使用注释 */
#define OW "Consistency is the last refuge of the unimagina\
tive. - Oscar Wilde" // 反斜杠把该定义延续到下一行

#define FOUR TWO*TWO
#define PX printf("X is %d.\n", x)
#define FMT "X is %d.\n"

int main() {
    
    

    int x = TWO;

    PX;
    x = FOUR;
    printf(FMT, x);
    printf("%s\n", OW);
    printf("TWO: OW\n");

    return 0;
}

Each line of #define (logical line) has 3 parts.

1. The first part is the #define directive itself.
2. The second part is the selected abbreviation, also known as a macro . There are macros that represent values ​​(in this case), these are called object-like macros . The C language also does not allow spaces in the names of function-like macros , and must follow the naming rules of C variables.
3. The third part is called the substitution list or substitution body . Once the preprocessor finds an instance of a macro in a program, it replaces the macro with the substitution body. The process of going from a macro to the final replacement text is called macro expansion . Note that standard C comments can be used on #define lines, each comment will be replaced by a space.

insert image description here

A macro can represent an explicit constant, any string, or even an entire C expression. Note however that although PX is a string constant, it only prints a variable named x.

Since the compiler evaluates all constant expressions (expressions containing only constants) at compile time, the preprocessing does not perform the actual multiplication, which happens at compile time. Preprocessing doesn't do calculations, it doesn't evaluate expressions, it just does substitutions.

1.3 Using parameters in #define

Use parameters in #define to create function-like macros that look and act like functions. Macros with parameters look a lot like functions because they also use parentheses. A function-like macro definition may have one or more arguments enclosed in parentheses, which then appear in the substitution body.

1.4 File contains: #include

When the preprocessor finds the #include directive, it will look at the following file name and include the contents of the file into the current file, that is, replace the #include directive in the source file. This is equivalent to entering the entire contents of the included file into the source file where the #include directive is located.

The #include directive comes in two forms:

#include<stdio.h> // 文件名在尖括号中
#include "hot.h"  // 文件名在双引号中

The angle brackets tell the preprocessor to look for files in the standard system directories. The double quotes tell the compiler to first look for the file in the current directory (or the directory specified by the filename), and if not found then look in the standard system directories.

The C language habitually uses the .h suffix to indicate header files, which contain information that needs to be placed at the top of the program. Header files often contain some preprocessing directives. Some header files (such as stdio.h) are provided by the system, of course you can also create your own header files.

1.5 Other instructions

Programmers may prepare C programs and C library packages for different working environments. Different environments may use different code types. The preprocessor provides some instructions, and the programmer can generate portable code by modifying the value of #define. The #undef directive cancels the previous #define definition. #if, #ifndef, #else, #elif, and #endif directives are used to specify when to write those codes. The #line directive is used to reset line and file information, the #error directive is used to give error messages, and the #pragma directive is used to issue instructions to the compiler.

1.5.1 #undef directive

The #undef directive is used to "cancel" a #define directive that has been defined.

#define ITEM 400

#undef ITEM

The above definition will be removed. You can now redefine ITEM to a new value. Even though ITEM was not defined originally. Undefining ITEM still works.

1.5.2 Defined from the perspective of C preprocessing

When the processor recognizes identifiers, it follows the same rules as C variable naming. When the preprocessor finds an identifier in the preprocessor, it treats the identifier as defined or undefined. Defined here means defined by the preprocessor. An identifier is defined if it is the name of a macro created by a preceding #define directive in the same file and not closed with an #undef directive. If the identifier is not a macro, assuming a file-scope C variable, then the identifier is undefined to the preprocessor.

Defined macros can be object macros, including empty macros or function-like macros:

#define LIMIT 1000 //LIMIT是已定义的
#define GOOD	// GOOD是已定义的
#define A(X) ((-(X))*(X)) //A是已定义的
int q;	// q不是宏,因此是未定义的
#undef GOOD	// GOOD取消定义,是未定义的 

Note that the scope of a #define macro begins at its declaration position in the file until the #undef directive cancels the macro, or extends to the end of the file (the condition that is satisfied first of the two is the end of the macro scope). Also note that if the macro is imported through a header file, the position of the #define in the file depends on the position of the #include directive.

1.5.3 Conditional compilation

Conditional compilation can be created using other directives . That is, you can use these directives to tell the compiler to execute or ignore blocks of information depending on the condition when

1.5.3.1 #ifdef, #else, and #endif directives

The #ifdef instruction indicates that if the preprocessor has defined the following identifier, execute all instructions before the #else or #endif instruction and compile all C codes (where the instruction appears first). If the preprocessor is undefined and there is a #else directive. Then execute all codes between #else and #endif.

#ifdef TITLE // 如果已经用#define定义了TITLE,则执行下面的代码
	#include "time.h"
	#define START 3
#else	// 如果没有用#define定义TITLE,则执行下面的指令
	#include "cow.h"
	#define START 5
#endif

1.5.3.2 #ifndef

The #ifndef directive is similar to the usage of the #ifdef directive, and can also be used with #else and #endif, but their logic is reversed. The #ifndef directive determines whether the following identifier is undefined, and is often used to define previously undefined constants.

#ifndef SIZE
	#define SIZE 30
#endif
#ifndef _STDIO_H
#define _STDIO-H


# endif

1.5.3.3 #if and elif directives

The if instruction is much like the if in C language. #if is followed by an integer constant expression, if the expression is not non-zero, the expression is true, and C relational operators and logical operators can be used in the instruction.

#if SYS == 1
#include "TIME.h"
#endif
#if defind (IBMPC)
	#include "TIME.h"
#elif defind (VAC)
	#include "VAX.h"
#endif

Two, C library

2.1 Math library

The math library contains many useful math functions, and the math.h header file provides prototypes for these functions. For the functions in math.h, note that the angles involved in the functions are all in radians (1 radian = 180/Π = 57.296 degrees)

insert image description here

2.2 Assertion library

The assertion library supported by the assert.h header file is a small library used to aid in debugging programs. It consists of the assert() macro, which receives an integer expression as a parameter. If the value of the expression is false, the assert() macro writes an error message to the standard error stream (stderr) and calls the abort() function Terminate the program (the prototype of the abort() function is in the stdlib.h header file). The assert () macro is to identify the key position in the program where certain conditions are true. If one of the specific conditions is false, the assert () statement is used to terminate the program. Usually the argument to assert() is a conditional or logical expression. If assert() terminates the program, it will first display the failing test, including the test's filename and line number.

#include <stdio.h>
#include "stdlib.h"
#include "math.h"
#include "assert.h"

int main() {
    
    

    int x, y, z;
    puts("please enter a number:\n");
    scanf("%d %d", &x, &y);

    if(y == 0){
    
    

        assert(y == 0);
        puts("error");
    }
    
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_46292926/article/details/127988262