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:
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 '##'
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.
3. Some special cases of '#' and '##'
1. Merge anonymous variable names
2. Fill the structure
[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".
Stringizing Operator (#)
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
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