C language - program environment and preprocessing

Program environment and preprocessing

1. Program translation environment and execution environment

In any implementation of ANSI C, there are two distinct environments. (ANSI C is a standard for the C language introduced by the American National Standards Institute (ANSI) and the International Organization for Standardization (ISO). The first is a
translation environment, in which source code is converted into executable machine instructions.
The second is the execution environment, which is used to actually execute the code.

2. Compile and link

2.1 Compilation environment

insert image description here

  • Each source file that makes up a program is individually converted into object code through the compilation process.
  • Each object file is bundled together by a linker to form a single and complete executable program.
  • The linker also imports any functions used by the program in the standard C function library, and it can search the programmer's personal function library and link the functions it needs into the program.

2.2 Operating environment

The process of program execution:
1. The program must be loaded into memory. In an environment with an operating system: Generally this is done by the operating system. In a standalone environment, program loading must be arranged manually, possibly by placing executable code into read-only memory.
2. The execution of the program starts. Then call the main function.
3. Begin executing the program code. At this time, the program will use a runtime stack (stack) to store the local variables and return address of the function. Programs can also use static memory. Variables stored in static memory retain their values ​​throughout the execution of the program.
4. Terminate the program. Normal termination of the main function.

3. Preprocessing

3.1 Predefined symbols

__FILE__ //进行编译的源文件
__LINE__ //文件当前的行号
__DATE__ //文件被编译的日期
__TIME__ //文件被编译的时间
__STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义

These predefined symbols are built-in to the language.
For example:

int main()
{
    
    
	printf("%s\n", __FILE__);
	printf("%d\n", __LINE__);
	printf("%s\n", __DATE__);
	printf("%s\n", __TIME__);
	
	return 0;
}

insert image description here

3.2 #define

3.2.1 #define definition identifier

Syntax: #define name stuff

For example:

#define  MAX    100000
#define reg register       //为 register这个关键字,创建一个简短的名字

If the defined stuff is too long, it can be written in several lines. Except the last line, a backslash (line continuation character) is added after each line.

3.2.2 #define define macro

The #define mechanism includes a provision that allows theparameterSubstituted into the text, this implementation is often called a macro (macro) or a definition macro (define macro).

Syntax: #define name(parament-list) stuff
among themparament-list is a comma-separated list of symbols that may appear in stuff.

Note:
The left parenthesis of the parameter list must be adjacent to name.
If any whitespace exists between the two, the argument list is interpreted as part of the stuff.

For example:

#define  SQUARE(x)   x*x
int main()
{
    
    
	int a = 5 ;
	printf("%d\n", SQUARE(a+1));
	return 0;
}

At a glance, this code may feel that the result is 36, but the actual output result is 11.
insert image description here

That's because the code was replaced with the following code in the preprocessing stage

	printf("%d\n", a + 1 * a + 1);

* has a higher priority than +, so the above situation occurs.

The solution to this problem is to add a pair of parentheses around the macro definition expression.

#define  SQUARE(x)   (x)*(x)

The result is naturally 36.

3.2.3#define substitution rules

There are several steps involved when expanding #defines to define symbols and macros in a program.

  • When calling a macro, the arguments are first checked to see if they contain any symbols defined by #define. If yes, they are replaced first.
  • The replacement text is then inserted into the program in place of the original text. For macros, parameter names are replaced by their values.
  • Finally, the resulting file is scanned again to see if it contains any symbols defined by #define. If yes, repeat the above processing.
    Notice
  • Other #define-defined symbols can appear in macro parameters and #define definitions. But with macros, recursion cannot occur.
  • When the preprocessor searches for symbols defined by #define, the contents of string constants are not searched.

3.2.4 Comparison between macros and functions

Attributes #defineDefine macros function
code length Macro code is inserted into the program each time it is used. Except for very small macros, the length of the program can grow substantially The function code appears in only one place; every time the function is used, the same code in that place is called
execution speed faster There is additional overhead for function calls and returns, so it is relatively slow
operator precedence The evaluation of macro parameters is in the context of all surrounding expressions. Unless parentheses are added, the precedence of adjacent operators may have unpredictable consequences, so it is recommended to use more parentheses when writing macros Function parameters are only valued once when the function is called, and its result value is passed to the function. The result of evaluating an expression is more predictable
Parameters with side effects Parameters may be substituted in multiple places in the macro body, so parameter evaluation with side effects may produce unpredictable results Function parameters are only evaluated once when passing parameters, and the result is easier to control
Parameter Type The parameters of the macro have nothing to do with the type, as long as the operation on the parameters is legal, it can be used for any parameter type The parameters of a function are related to the type. If the types of the parameters are different, different functions are required, even if they perform the same task.
debugging Macros are inconvenient to debug Functions can be debugged statement by statement
recursion Macros cannot be recursive functions can be recursive

3.3 #undef

This command is used to remove a macro definition.
For example:

#define  M  100
#include<stdio.h>
int main()
{
    
    
	printf("%d\n", M);

	return 0;
}

insert image description here

#undef M 
	printf("%d\n", M);

insert image description here

Guess you like

Origin blog.csdn.net/st200112266/article/details/127366923