Pre-processing review

1. The translation environment of the program
In this environment, the source code is converted into executable machine instructions.

2. The execution environment of the program
It is used to actually execute the code.

3. Detailed explanation: C language program compilation + linking
Insert picture description here
. Each source file that composes a program is converted into object code through the compilation process.
Each object file is bundled together by the linker to form a single and complete executable program.
The linker will also introduce any function used by the program in the standard C function library, and it can search the programmer's personal library, and link the functions it needs to the program.
Insert picture description here
Insert picture description here
1 The preprocessing option gcc -E test.c -o test.i stops after the preprocessing is completed, and the results produced after the preprocessing are all placed in the test.i file.
2. After test.c gcc -S compiler option compiled stopped, the result is stored in test.s in.
3. compilation gcc -c test.c stopped after completion of compilation, stores the result in test.o in.
test.c---->test.i----> test.s---->test.o is converted into a test.exe file after linking.
This process is pre-compilation, compilation, and assembly plus link processing files the process of.
In the pre-compilation/pre-processing process:
①#include header file inclusion ②Comment
deletion (use spaces to replace comments)
③#define (replacement has been started here)
④test.c----test.i
compilation:
①test .i---test.s translates c code into assembly code
②Analysis of grammar, morphology, semantics, summary of symbols

4. Introduction to predefined symbols
These predefined symbols are built-in language

int main()
{
    
    
	printf("%s\n",__FILE__);//进行编译的源文件 (当前文件的绝对路径)
	printf("%d\n", __LINE__); //文件当前的行号
	printf("%s\n", __DATE__); //文件被编译的日期
	printf("%s\n",__TIME__); //文件被编译的时间
	printf("%s\n",__FUNCTION__);//主函数名
	//__STDC__; //如果编译器遵循ANSIC,其值为1,否则未定义,对于傲娇的VS编译器是不能识别这个预处理符号的。
	return 0;
}

Insert picture description here

5. Preprocessing directive #define
#define defines the identifier

#define MAX 100
#define STR "hehe"  // 定义字符串
#define reg register//为register这个关键字,创建一个简短的名字 

Question:
When defining the identifier in define, do you need to add ;?
Answer: You don’t need to add a';', because once you don’t write that time, you will report the error. So in order to avoid this kind of thing from happening, it is unified It is best not to add';'.

6. Comparison of macros and functions

#define SQUARE(X) X*X
int main()
{
    
    
	int ret = SQUARE(5); // 宏气的作用是替换,把X替换为5,然后作后面的5*5运算
	int ret = SQUARE(5 + 1);// 5+1*5+1 = 5+5+1 = 11
	return 0;
}

The role of macros is to "replace". It is generally agreed that when writing macros, it will be written in uppercase. In order to avoid that the results of some expressions are not the same as expected, it is best to add () when writing macros.

E.g

#define SQUARE(X) (X)*(X)

#define Replacement rules
When expanding #define to define symbols and macros in a program, several steps are involved.

  1. When calling the macro, first check the parameters to see if it contains any symbols defined by #define. If they are, they are replaced first.
  2. The replacement text is then inserted at the position of the original text in the program. For macros, the parameter names are replaced by their values.
  3. Finally, scan the result file again to see if it contains any symbols defined by #define. If yes, repeat the above process.
    Note:
    ① The variables defined by other #define can appear in the macro parameters and #define definition. But for macros, recursion cannot occur.
    ② When the preprocessor searches for the symbol defined by #define, the content of the string constant is not searched.

7. Introduction
to preprocessing operators # and ## How to insert parameters into a string?
Wrong way

#define PRINT(X) printf("the value of X is %d\n",X)
int main()
{
    
    
	int a = 10;
	int b = 20;
	PRINT(a);  // the value of X is 10
	PRINT(b);  // the value of X is 20
	//结果是错误的,我希望X的位置可以被替换成'a' 和 'b'
	return 0;
}

The correct wording introduces'#', which is equivalent to converting this character into a corresponding string, and for strings, it will connect the strings together by default (strings are automatically connected.
)


#define PRINT(X) printf("the value of "#X" is %d\n",X)
int main()
{
    
    
	int a = 10;
	int b = 20;
	PRINT(a);  //the value of a is 10 
	PRINT(b);  // the value of b is 20
	return 0;
}

##的
效应##The symbols on both sides of it can be combined into one symbol. It allows macro definitions to create identifiers from separate text fragments.

#define CAT(X,Y) X##Y
int main()
{
    
    
	int Class84 = 2019;
	printf("%d\n", CAT(Class, 84));
	//printf("%d\n",Class##84);
	//printf("%d\n",Class84);
	//所以结果是   2019
	return 0;

Tip: Macros sometimes have side effects (don’t write ++ or – symbols in macros easily) to
calculate the result?

#define MAX(X,Y)   (X)>(Y)?(X):(Y)
int main()
{
    
    
	int a = 10;
	int b = 11;
	int max = MAX(a++, b++);
	//int max = ((a++)>(b++)?(a++):(b++));//再次声明完全替换
	//第一个表达式是先使用后++。然后a和b的值就都改变了,到后面的b++这里的b=12,使用完就是13
	printf("%d\n", max); //12
	printf("%d\n", a);//11
	printf("%d\n", b);//13
	return 0;
}

Comparison of Macros and Functions
Macros are usually used to perform simple operations. For example, find the larger of two numbers.

#define MAX(a, b) ((a)>(b)?(a):(b))
int max(int x,int y)
{
    
    
	return (x>y?x:y);
}

Then why not use functions to accomplish this task? There are two reasons:

  1. The code used to call the function and return from the function may take more time than the actual execution of this small calculation work. So macros are better than functions in terms of program size and speed.
  2. More importantly, the parameters of the function must be declared as specific types. So functions can only be used on expressions of the appropriate type. On the contrary, how can this macro be applied to integer, long integer, floating point, etc. can be used to compare types. Macros are type independent.

Of course, compared with macros, functions also have disadvantages:

  1. Every time a macro is used, a code of the macro definition will be inserted into the program. Unless the macro is relatively short, it may greatly increase the length of the program.
  2. Macros cannot be debugged.
  3. Macros are not rigorous enough because they are type-independent.
  4. Macros may cause problems with operator precedence, making the process prone to errors. Macros can sometimes do things that functions cannot. For example: Macro parameters can have types, but functions cannot.

Macros can be typed!

#define SIZEOF(type) sizeof(type)

int main()
{
    
    
	int ret = SIZEOF(int);
	//int ret = sizeof(int);
	printf("%d\n", ret);
	return 0;
}
#define MALLOC(num,type) (type*)malloc(num*sizeof(type))


int main()
{
    
    
	int* p = (int*)malloc(10 * sizeof(int));
	int* p = MALLOC(10, int);
  //int* p = (int*)malloc(10*sizeof(int));
	return 0;
}

Insert picture description here
Naming Convention
Generally speaking, the syntax for using function macros is similar. So language itself cannot help us distinguish between the two. One of our usual habit is to capitalize all macro names and not all capitalize function names.

#undef
This instruction is used to remove a macro definition.

8. Conditional compilation It
is very convenient if we want to compile or abandon a statement (a group of statements) when compiling a program. Because we have conditional compilation instructions.

Debugging code is a pity to delete and keep it in the way, so we can selectively compile it.

#include <stdio.h>
#define DEBUG
int main()
{
    
    
	int arr[10] = {
    
    1,2,3,4,5,6,7,8,9,10};
	int i = 0;
	for(i=0;i<10;i++)
	{
    
    
		arr[i] = 0;
#ifdef DEBUG //如果定义了DUBUG 那就执行下面的语句
//#if defined(DEBUG) 和上面的意思是一样的。
//#ifndef DEBUG 相反的意思,如果没有定义,那就执行下一条语句
		printf("%d ",arr[i]);
#endif

#ifdef 1 // 如果是1那就是真,执行下面的语句,为0是假,不执行下面的语句
		printf("%d ",arr[i]);	
#endif
	}
	return0;
}

Conditional compilation of multiple branches

int main()
{
    
    
#if 1==2
	printf("haha\n");
#elif 1==2
	printf("hehe\n");
#else
	printf("heihei\n");
#endif
	return 0;
}

Nested instructions

#if defined(OS_UNIX)  
		#ifdef OPTION1  
				 unix_version_option1(); 
 		#endif  #ifdef OPTION2  
  				 unix_version_option2(); 
   		#endif 	
#elif defined(OS_MSDOS) 
     	#ifdef OPTION2   
   			 	 msdos_version_option2(); 
        #endif 
#endif

9. The preprocessing directive #include
includes library files "<>"
includes local files (custom files) "" to include,

Search strategy:
first search in the directory where the source file is located. If the header file is not found, the compiler searches for the header file in the standard location just like searching for the library function header file. If you can't find it, it will prompt a compilation error.

Sometimes it is inevitable to include the same header file multiple times, and it will be called multiple times, increasing the running time of the program. In order to better avoid this problem, you can write in the header file

#ifndef __TEST_H__
#define __TEST_H__
//头文件的内容
#endif

or

#pragma once

You can avoid the repeated introduction of header files.

Preprocessed name
Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/MEANSWER/article/details/110484840