Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Preprocessing of C language

2025-02-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)06/01 Report--

1 # define name value

I then learned that the direct driving force of preprocessing is to look at the source code of php, the beginning of a large number of macro definers, the previous' master 'the use of # define is too few to understand the processing logic and running path of macros in the source code. So it is necessary to re-learn the preprocessor, a lot of things in it are not difficult, but you do not have access to it, and when you learn, it will feel easy.

I. pits in use and definition of macros

This section is in the form of giving the code first and then explaining it, so you can see if each code works as you expected!

What a macro is, a macro is the text in which the specified parameters are replaced by the # define mechanism. This way of implementation is a macro. Using macro definitions, you can extract frequently called functions to speed up execution. The definition is as follows: # define name (parameter) executor. "parameters" can be a comma-separated list of parameters that can be applied to the execution. It must be noted that the left parenthesis of the "parameters" must be adjacent to the macro name, otherwise the editor will report an error or be interpreted as part of the execution. For example, if you write a TEST (a) a * a call to execute, write that TEST (1) actually executes the replaced 1 * 1.

Everything has its advantages and disadvantages. Macro definition is easy to use and has incomparable execution speed, but there are many holes in macro definition. Let's talk about this pit. Look at the following code:

1 # include 2 3 # define TEST (a) a * a 4 5 int main () {6 int b = TEST (2); 7 int c = TEST (1x2); 8 printf ("baked% d, cased% d", b, c); 9 printf ("\ n\ n"); 10}

What is the result you can feel without execution? A lot of people say without thinking: baked 4Jet clocked 9. If this is the case, there will be no pit, the actual print out is: baked 4, clocked 5, why the value of c and expected deviation, in fact, you replace the value of the implementation body to try, it is not difficult to find the problem, when entering 1: 2, macro replaced by 1: 2: 1: 2, of course, it is 5. Okay, I see. Have you learned it? Learn to look at another one:

1 # include 2 3 # define TEST (a) (b) (a) > (b)? (a): (B) 4 5 int main () {6 int zyf= 1; 7 int abc= 2; 8 int ret= TEST (zyf++, abc++); 9 printf ("zyf=%d,abc=%d,ret=%d", zyf, abc, ret); 10 printf ("\ n\ n"); 11}

How much is the output? it would be wrong if it is zyf=2,abc=3,ret=3. The actual result is: zyf=2,abc=4,ret=3. The truth is the same as before, only by looking at the results of the replacement can we really see the answer.

Such a problem is difficult to prevent, how can we solve it? in fact, the solution is very simple, the wrong reason is that the order of execution is different from what we expected, then adding parentheses should solve this problem. For example, (a) * (a). In fact, this is not the most comprehensive way, for example, if you look at this: ADD (a) (a) + (a), if you call it like this: ADD (2) * 5, it will not work again, and it will be replaced by (a) + (a) * 5. The order of execution is still different from what you expected, so you have to add parentheses to the outermost layer: (a) + (a), so it is solved.

II. Predefined symbols

There are several predefined symbols in C language, so it is necessary to talk to you last time. First, look at a piece of code:

1 # include 2 # include 3 # define VAR_DUMP printf (\ 4 "[\ n\ tfile:%s\ n"\ 5 "\ tline:%d\ n"\ 6 "\ ttime:%s% s\ n"\ 7 "\ tvalue:%d\ n]",\ 8 _ FILE__, _ _ LINE__, _ _ DATE__, _ TIME__, value\ 9) 10 int main () {11 int value = 1 12 VAR_DUMP;13 printf ("\ n\ n"); 14}

Is it a little different from what you learned in college? the simplest macro definition can be defined in the form of # define name value, or you can write the value as a function that replaces the function directly at run time. This macro definition encapsulates the debugging method so that the contents of the variable can be printed like the var_dump () or print_r () function in PHP.

There are several things you can learn from this code:

1. Use # define to replace any text into the program, and you are free to use VAR_DUMP in the main program.

2, the macro definition does not end with a semicolon, if the macro definition is very long, you can add a backslash at the end to keep the code readable.

3. You can define frequently called functions as macros, which can speed up the execution. The specific reasons will be discussed later.

4. C language has several predetermined symbols that we need to know, which are very useful in many cases:

_ _ precompiled file name of FILE__

The line number of the current line of the LINE__ file (executed to this line)

_ _ date when the DATE__ file was compiled

Specific time of compilation of _ _ TIME__ file

Whether _ _ STDC__ complies with ANSI C (not commonly used)

Finally, the running result is attached, as shown in the figure:

III. The process of macro replacement

In the compilation phase of a program, macros are replaced first, which generally involves the following steps:

1. The place where the macro is called depends on whether there is a # define definition, and if so, replace it.

2. Insert the replacement text information into the replacement position, where the parameter is replaced with the actual value.

3. # define can contain other defined things defined by # define, but it should be noted that there can be no recursion.

Because there is an automatic combination of adjacent fields in substitution, there are some clever schemes that can be used:

1 # include 2 # include 3 4 # define VAR_DUMP (A Magi B)\ 5 printf ("Value of" # B "is" A "\ n", B) 6 7 int main () {8 int x = 1; 9 VAR_DUMP ("% d", Xerox 2); 10}

Conditional compilation and other macro uses

You can see a lot of conditional compilation in large C programs, such as loading different macro configurations according to the current environment, or adding straight-pole default compilation conditions when compiling. The implementation of these things is inseparable from conditional compilation.

1. Condition nesting, # if # endif prototype:

1 # if condition2 executor 3 # endif

Condition can be used to determine whether the executor wants to execute or not, so as to control the compilation into different systems in different environments. Look at the following code. When DEBUG is defined as a non-zero value, the MAX macro definition exists, and when it is defined as 0, the program will report an error.

1 # include 2 3 # define DEBUG 0 4 # if DEBUG 5 # define MAX (a) ((a) * (a)) 6 # endif 7 8 int main () {9 int b = MAX (2); 10 int c = MAX (1 # 2); 11 printf ("baked% d, cased% d", b, c); 12 printf ("\ n\ n"); 13}

Of course, # if can also be used in nesting with # elif, which is the same as using if else in the function. Here is a passage from a php source code. You can see that compiling php specifies different parameters, checking different environments, and so on can be completed by conditional compilation in preprocessing.

1 # ifndef PHP_H 2 # define PHP_H 3 4 # ifdef HAVE_DMALLOC 5 # include 6 # endif 7 8 # define PHP_API_VERSION 20100412 9 # define PHP_HAVE_STREAMS10 # define YYDEBUG 01112 # include "php_version.h" 13 # include "zend.h" 14 # include "zend_qsort.h" 15 # include "php_compat.h" 16 # include "zend_API.h "17 18 # undef sprintf19 # define sprintf php_sprintf20 21 / * PHP's DEBUG value must match Zend's ZEND_DEBUG value * / 22 # undef PHP_DEBUG23 # define PHP_DEBUG ZEND_DEBUG24 25 # ifdef PHP_WIN3226 # include" tsrm_win32.h "27 # include" win95nt.h "28 # ifdef PHP_EXPORTS29 # define PHPAPI _ declspec (dllexport) 30 # else31 # define PHPAPI _ _ declspec (dllimport) 32 # endif33 # define PHP_DIR_SEPARATOR'\'34 # define PHP_EOL "\ r\ n" 35 # else36 # if defined (_ _ GNUC__) & & _ _ GNUC__ > = 437 # define PHPAPI _ attribute__ ((visibility ("default") 38 # else39 # Define PHPAPI40 # endif41 42 # define THREAD_LS43 # define PHP_DIR_SEPARATOR'/'44 # define PHP_EOL "\ n" 45 # endif46 47 # ifdef NETWARE48 / * For php_get_uname () function * / 49 # define PHP_UNAME "NetWare" 50 # define PHP_OS PHP_UNAME51 # endif52 53 # if HAVE_ASSERT_H54 # if PHP_DEBUG55 # undef NDEBUG56 # else57 # ifndef NDEBUG58 # define NDEBUG59 # endif60 # endif61 # include 62 63 # else / * HAVE_ASSERT_H * / 64 # define assert (expr) ((void) (0)) 65 # endif / * HAVE_ASSERT_H * / 66 67 # define APACHE 068 # if HAVE_UNIX_H69 # include 70 # endif71 72 # if HAVE_ALLOCA_H73 # include 74 # endif75 76 # if HAVE_BUILD_DEFS_H77 # include 78 # endif79. . .

2. Whether it has been defined

Defined: # if define () or # ifdef

Not defined: # if! define () or # ifndef

Although the former is not written as refined as the latter, the former has more usage scenarios, such as the following, which can be nested.

1 # if defined (DEBUG) 2 # ifdef DEBUGTWO3 # define TEST (a) a * a4 # endif5 # endif

3. Remove a macro definition. When you no longer use a macro definition, you can use undef to remove unwanted macros. Prototype:

1 # undef name

V. Macro naming rules and differences from functions

From the previous use, we can see that the rules for the use of macros are exactly the same as functions, but there are differences in nature. How to distinguish macros from functions in use involves code specifications and code readability. The standard use of macros should be in uppercase letters, so that using macros anywhere in the program will know that this is a macro definition. For example, # define TEST (a) ((a) * (a)) was used earlier.

There are the following differences between macros and functions:

1. In terms of execution speed, the definition of macros is faster, and functions are slower than macros because of the need for call stack and the overhead of calling, returning, and saving the site.

2, the code length, macros in the code length is actually growing, every use of macros will replace name with macro content, if a large number of use, the code will grow significantly, the new channel IELTS training function code is only one, more save code space.

3. In terms of parameter types, macros have no parameter types, as long as they can be used. The function is different, the function has the parameter type certainty. Formally, because of this, some macros can skillfully take advantage of this to complete the tasks that the function cannot accomplish. See the following code (seen in the book), and skillfully take advantage of the unlimited transfer type to automatically open up various types of space you want:

1 # include 2 # include 3 4 # define CREATE_P (nums, type) ((type *) malloc ((nums) * sizeof (type) 5 6 int main () {7 int nums = 2 type 8 CREATE_P (nums, int); 9}

4, macro definition and function use scenario, macro definition is generally at the beginning of the program, functions into macro definitions must consider the cost, short and concise functions into macros are best used, the function responsible for the conversion of functions into macros is a bit of a loss outweighs the gain.

VI. The document contains

1. Local file inclusion and library file inclusion

File inclusion is bound to be used in large systems, and there are so many macro definitions in large systems that it is impossible to copy all macro definitions to every file, so file inclusion can solve this problem.

In fact, the editor supports two kinds of file inclusion, one is the inclusion of library files that we often use, such as the one we saw above: # include, and the other is local file inclusion. To put it bluntly, it is a file written by ourselves, and the prototype is as follows:

1 # include 2 # include "filename"

These two ways can be used for file inclusion, the difference is that the first is the library file inclusion, the standard C library functions will end with the .h extension, the second is the local file inclusion, when the editor sees the second way, give priority to looking for the local library file under this path, if it is not found, it will be found in the specified path as the library file, then the second and the first kind of almost. The second method of inclusion is also good in coding habits, and it is easy for others to know whether the file is a library function or written by you when looking at your code.

1. Nested files contain

Large systems contain not only a large number of files, but also a large number of nested files. Take a look at the following example:

The a.hrecrum b.hpr. Hjre define.c file, in which the contents of the arecald brecronomec define file are as follows:

1 a.h: 2 # include "c.h" 3 void var_dumpa () {4 test obja; 5 obja.a [1] = 2; 6 printf ("obja.a [1]:% d\ n", obja.a [1]); 7} 8 9 b.h:10 # include "c.h" 11 void var_dumpb () {12 test objb;13 objb.a [1] = 2 14 printf ("objb.a [1]:% d\ n", objb.a [1]); 15} 16 17 c.h:18 # include 19 # include 20 21 typedef struct test {22 int a [10]; 23} test;24 25 define.c:26 # include 27 # include "a.h" 28 # include "b.h" 29 30 int main () {31 var_dumpa (); 32 var_dumpb (); 33 printf ("\ n\ n"); 34}

The ab file contains the c file, and the define.c file will cause an error after referencing the ABI file: the typedef struct test type error, because the c.h file is included twice, which is often encountered in large systems, or you will find that repeated references to the library file will not report an error, so it can be seen that the library file must have used a solution. In fact, the solution to this error is to use conditional compilation. When this file is introduced into another file, we can set a macro definition, such as:

1 # include 2 # include 3 4 # ifndef PATH_C_H5 # define PATH_C_H 16 typedef struct test {7 int a [10]; 8} test;9 # endif

Because each compilation compiler will read the entire header file, if all files are compiled with this condition, the problem of duplicate macro compilation caused by cross-reference files will be solved, as follows:

All right, that's it, rearranging the understanding and basic use of macro definitions. Time is in a hurry, please point out the mistakes, thank you very much!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report