C Advanced Cultivation Notes - Cultivation Notes 25: Analysis of # and ## Operators

--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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325640315&siteId=291194637