The usage of "#" and "##" in C language macro

The usage of "#" and "##" in C language macros 
In the process of viewing the Linux kernel source code, I encountered many macros, many of which involve "#" and "##". Therefore, I searched on the Internet. Some information is organized as follows:
1. General usage 
We use # to convert macro parameters into a string, and use ## to fit two macro parameters together.
usage:
#include <iostream>
#include <cstdio>
#include <climits>

using namespace std;

#define STR(s)     #s
#define CONS(a,b)  int(a##e##b)

intmain()
{
    printf(STR(vck)); // print the string "vck"
    printf("%d\n", CONS(2,3)); // 2e3 output: 2000
    return 0;
}

The output is as follows:

vck
2000


2. When the macro parameter is another macro, it 
should be noted that the macro parameter will not be expanded where there is a '#' or '##' in the macro definition.
1. Cases other than '#' and '##'

#define TOW      (2)
#define MUL(a,b) (a*b)

printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
The macro on this line will expand to:
printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
The parameter TOW in MUL will be expanded to (2).

2. When there is '#' or '##'

#define A          (2)
#define STR(s)     #s
#define CONS(a,b)  int(a##e##b)

printf("int max: %s\n",  STR(INT_MAX));    // INT_MAX #include<climits>
This line will expand to:
printf("int max: %s\n", "INT_MAX");

printf("%s\n", CONS(A, A));               // compile error  
This line is:
printf("%s\n", int(AeA));

Neither INT_MAX nor A will be expanded, but the solution to this problem is simple, adding an extra layer of intermediate conversion macros.
The purpose of adding this layer of macros is to expand all macro parameters in this layer, then the macro (_STR) in the conversion macro can get the correct macro parameters.
#define A           (2)
#define _STR(s)     #s
#define STR(s) _STR(s) // Conversion macro
#define _CONS(a,b)  int(a##e##b)
#define CONS(a,b) _CONS(a,b) // conversion macro

printf("int max: %s\n", STR(INT_MAX)); // INT_MAX, the maximum value of int type, is a variable #include<climits>
The output is: int max: 0x7fffffff
STR(INT_MAX) --> _STR(0x7fffffff) and then convert it to a string;

printf("%d\n", CONS(A, A));
The output is: 200
CONS(A, A)  -->  _CONS((2), (2))  --> int((2)e(2))

3. Some special cases of '#' and '##'
1. Merge anonymous variable names
#define ___ ANONYMOUS1 (type, var, line) type var ## line
#define  __ANONYMOUS0(type, line)  ___ANONYMOUS1(type, _anonymous, line)
#define  ANONYMOUS(type)  __ANONYMOUS0(type, __LINE__)
Example: ANONYMOUS(static int); That is: static int _anonymous70; 70 indicates the line number of the line;
The first layer: ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
Second layer: --> ___ANONYMOUS1(static int, _anonymous, 70);
The third layer: --> static int _anonymous70;
That is, only the macros of the current layer can be unlocked each time, so __LINE__ can only be unlocked in the second layer; 

2. Fill the structure
#define  FILL(a)   {a, #a}

enum IDD{OPEN, CLOSE};
 
typedef struct MSG{
    IDD id;
    const char * msg;
}MSG;

MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
is equivalent to:
MSG _msg[] = {{OPEN, "OPEN"}, {CLOSE, "CLOSE"}};
3. Record file name
#define  _GET_FILE_NAME(f)   #f
#define  GET_FILE_NAME(f)    _GET_FILE_NAME(f)
static char  FILE_NAME[] = GET_FILE_NAME(__FILE__);
4. Get the string buffer size corresponding to a numeric type
#define  _TYPE_BUF_SIZE(type)  sizeof #type
#define  TYPE_BUF_SIZE(type)   _TYPE_BUF_SIZE(type)
char  buf[TYPE_BUF_SIZE(INT_MAX)];
     -->  char  buf[_TYPE_BUF_SIZE(0x7fffffff)];
     -->  char  buf[sizeof "0x7fffffff"];
This is equivalent to: char buf[11];

[alps_008]: I
basically read it once. The landlord's situation belongs to general usage: "#change the macro parameter into a string, and use ## to fit the two macro parameters together".
#include <stdio.h>
#include <string.h>

#define STRCPY(a,b) strcpy(a##_p,#b) //Add the character _p after the first parameter, and turn the second parameter into a string

intmain()
{
    char var1_p[20];
    char var2_p[30];
    
    strcpy(var1_p,"aaaa");
    strcpy(var2_p,"bbbb");
    
    STRCPY(var1,var2); //equal to strcpy(var1_p,"var2");
    STRCPY(var2,var1); //equal to strcpy(var2_p,"var1");
    
    printf("%s\n",var1_p);
    printf("%s\n",var2_p);
    
    return 0;
}

【jeffer007】:
Token-Pasting Operator (##) 

// preprocessor_token_pasting.cpp

#include <stdio.h>

#define paster(n) printf_s("token" #n " = %d", token##n)

int token9 = 9;

intmain()
{
    paster (9);
}

//Output
token9 = 9

Stringizing Operator (#) 
// stringizer.cpp

#include <stdio.h>

#define stringer( x ) printf( #x "\n" )

intmain()
{
    stringer( In quotes in the printf function call );
    stringer( "In quotes when printed to the screen" );   
    stringer( "This: \"  prints an escaped double quote" );
}

//Output
In quotes in the printf function call
"In quotes when printed to the screen"
"This: \"  prints an escaped double quote"

Reprinted from: http://www.cnblogs.com/hnrainll/archive/2012/08/15/2640558.html


Guess you like

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