You must know the details of C language preprocessing

  • 2020-04-01 21:39:30
  • OfStack

The C language preprocessor performs macro substitution, conditional compilation, and file inclusion. It is common to use a prompt beginning with "#". The following is the application of C language preprocessing:

1. Trigraph Sequences

The character Set of the C source program is contained in the seven-bit ASCII character Set, but it is a superset of ISO 646-1983 Invariant Code Set. In order for the program to be rendered in a reduced set, the following triletter words are replaced with the corresponding single character.

Three letter word A single character ?? = # ?? / \ ?? ' ^ ?? ( [ ?? ] ?? ! | ?? < { ?? > } ?? - ~

The substitution occurs before any other processing.

For example, if you try to print the string "what?? !"


 printf("what??!n");

You get the string "what|".

If you comment your code this way, you'll be surprised:


// Will the next line be executed?????????????/
a++;

A++ is not executed. The premise is that you know the function.

Note: since the compiler has different support for ANSI C, some compilers will treat three-letter words as normal characters, so you need to add "-trigraphs" to the compilation option.

2. Line joining together

A line ending with a backslash "\" concatenates that line with the next line (the job of the preprocessor is to remove the backslash '"\" and the following newline character '\n'). ['\' is called line continuation]

For example, you could write it like this


/
* is a legal comment. *
/

Macro definition and expansion

A) simple macro substitution

Simple macro substitution allows the program to represent a word string with an identifier in the form of:


#define  identifier   The word string 

An identifier (called a macro name) is defined as a string of words that follows. A word string (string for short) is any body that ends with a newline to replace the identifier in the program. If the string is too long to be written as multiple lines, there should be a line continuation at the end of each line except the last line (that is, a return after adding a "\").

Note: strings in the string constant that appear to be the same as the macro name are not in the substitution column. Such as:


#define YES 1
printf("YES");            //Print YES instead of 1

B) macro substitution with parameters

The form of pre-processing instruction is:


#define     identifier ( identifier , identifier ,..., identifier )     The word string 

"Identifier (identifier, identifier,... "Is the defined macro. The identifier outside () is called the macro name. The identifier in () is the formal parameter of the macro. There must be no space between the macro name and the () that follows it.

Such as:


#define max(a,b) ((a)>(b)? (a): (b))

The & # 9830; The operators # and ##

The operator # turns the string after it into a string surrounded by double quotes.

The operator ## combines two identifiers to form a new identifier


#define str(expr)    #expr
#define cat(x,y)      x ## y
int ab=12;
printf(str(hello world!));      //It will be replaced by printf("hello world!") );
printf("ab=%dn", cat(a,b));        //Will be replaced by printf("ab=% dn ", ab);   Output ab = 12

The & # 9830; The order in which macros are replaced

#include <stdio.h>
 #define f(a,b)  a##b
 #define g(a)   #a
 #define h(a)   g(a)

 int main()
 {
         printf("%sn", h(f(1,2)));
         printf("%sn", g(f(1,2)));
         return 0;
 }

The output is 12 and f(1,2). Why is that? Macros are not unwound like functions, from the inside out.

(1) the macro name or macro parameter name in "" is not replaced

(2) macro replacement order: a macro with parameters calls another macro internally, the parameter is also a macro, then replace the outer macro, then replace the parameters of the outer macro, and finally replace the inner macro.

Knowing these rules is not hard to understand when the above results appear.

Warm tips: when writing macro substitution instruction with parameters, the recommended practice is to use () to enclose each parameter in the word string, and the entire expression should also be enclosed with (); Otherwise, the substitution result may not be what you want, for example:


#define sqr(x)    x * x
//If the macros in the program are referenced in the form of
sqr(3.0+1.0);                //After preprocessing, it will be replaced with 3.0 + 1.0 * 3.0 + 1.0

The result is not equivalent to what you intended (3.0+1.0)*(3.0+1.0)

C) cancel macro definition


#undef  identifier 

Causes the macro name identifier to become undefined. If #undef is an undefined identifier   It doesn't cause errors.

4. File include


#include <filename>     //The header file that references the standard library (the compiler will search from the standard library directory)
#include "filename"       //Header files that reference non-standard libraries (the compiler will search from the user's working directory)
#include  identifier             //The identifier is defined by #define. Filename> Or the macro name of "filename"

5. Conditional compilation

Conditional compilation instruction format is as follows:


if-line  The body of the  
[#elif  Constant expression   The body of the ]
...
[#else  The body of the ]
#endif

If-line is any of the following forms:

(1) #if constant expression

(2) #ifdef identifier

(3) #ifndef identifier

The & # 9830; The defined operator is used to determine whether the identifier has been defined. The form is as follows:

Defined identifier

or

Defined (identifier)

The following

# ifdef identifier

# # ifndef identifier

Is equivalent to

# if defined identifier

# if! Defined identifier

6. The line of control

Line control instructions take the following two forms

(1) #line n "filename"

(2) #line n

Pretreatment line control function for other preprocessor of C source program (for example, the database system of host C precompiler) in tracking processor (for example by host C precompiler handling extension. PC precompiled source program) provide a convenient when the line number, to facilitate the end user's source program and the wrong. It causes the compiler to believe that n (decimal positive integer) is the line number of the next source line, and that "filename" is used as the current filename.

Generate errors

# error error_messageopt

Have the compiler output the error message error_message

8. Pragmas

# pragma token - sequenceopt

#pragma is an instruction defined at the time of the compiler's implementation, which allows various instructions to be passed from this to the compiler. For example, a compiler might have an option to support trace program execution, which can be selected with a #pragma statement. The compiler ignores the #pragma option, which it does not support. #pragma improves the portability of C source programs to compilers.

9. Empty instruction

like

#

Without any effect

10. Predefined macros

The C language has five built-in predefined macros, which are

S/s of the current source program

S/s file name of the program being compiled

Type of date string with the form of "Mmm dd yyyy"

S/s time string with the form of "hh:mm:ss"

If the content of arbitration is a decimal constant 1, then the implementation of the compiler conforms to standard C


Related articles: