--The difficulty of things is far less than the fear of things!
In this chapter, let's talk about the # and ## operators. Many people may not pay attention to these two operators. However, these two operators can often provide us with great convenience for development.
# operator:
- The # operator is used to convert macro arguments to strings during preprocessing
- The conversion of # is done during preprocessing, so it is only valid in macro definitions
- the compiler doesn't know the role of # conversion
The usage is as follows: #define STRING(x) #x
Look at the code below
#define STRING(x) #x intmain() { char *p = STRING(abc); return 0; }
The content of the precompiled file is as follows. We can see that the macro STRING(abc) we defined becomes the "abc" string after being processed by the preprocessor.
#line 1 "main.c" intmain() { char *p = "abc"; return 0; }
Knowing the basic usage of the # operator, let's take a look at the clever use of the # operator in engineering:
#include <stdio.h> //Through # and comma expressions, when we use macros, we can print out the name of the called function and execute the function #define CALL(f, p) (printf("Call function %s\n", #f), f(p)) int square(int n) { return n * n; } int func(int x) { return x; } intmain() { int result = 0; result = CALL(square, 4); printf("result = %d\n", result); result = CALL(func, 10); printf("result = %d\n", result); return 0; }
The compilation and execution results are as follows, isn't it very clever:
## operator:
The -## operator is used to concatenate two identifiers during preprocessing
The linking effect of -## is completed during preprocessing, so it is only valid in macro definitions
- the compiler does not know the linking effect of ##
用法:#define CONNECT(a,b) a##b
Let's see an example:
#define NAME(n) name##n intmain() { int NAME(1); int NAME(2); NAME(1) = 1; NAME(2) = 2; return 0; }
The content of the file processed by the preprocessor is:
#line 1 "main.c" intmain() { int name1; int name2; name1 = 1; name2 = 2; return 0; }
It can be seen from the preprocessed file that the ## operator has glued the name and n together.
Let's take a look at the typical usage in the project:
#define STRUCT(type) typedef struct _tag_##type type;\ struct _tag_##type STRUCT(Student) //Use the macro STRUCT to define a structure named Student, and then you can directly use the Student declaration to define the structure variable { char* name; int id; }; intmain() { Student s1; Student s2; s1.name = "s1"; s1.id = 0; s2.name = "s2"; s2.id = 1; return 0; }
We use the preprocessor to process it, and the content of the obtained file is as follows:
#line 1 "main.c" typedef struct _tag_Student Student; struct _tag_Student { char* name; int id; }; intmain() { Student s1; Student s2; s1.name = "s1"; s1.id = 0; s2.name = "s2"; s2.id = 1; return 0; }
Looking at it this way, isn't it very clear? It is also very convenient to define another structure, just directly STRUCT(structName).
Summarize:
The -# operator is used to convert macro arguments to strings during preprocessing
The -## operator is used to concatenate two identifiers during preprocessing
- the compiler does not know the existence of the # and ## operators
The -# and ## operators are only valid in macro definitions