Log output variable parameter macro usage record

#define COLOR_RED "\033[1, 31m"
#define COLOR_NONE "\033[0m"
#if DEBUG #define DBG_PRT(fmt, args...)\ do\ {\ printf(COLOR_RED"file:%s line:%s", __FILE__, __LINE__);\ printf(fmt,##args);\ }while(0)
#else
#define DGB_PRT(fmt, args...)
#endif

The above code is a macro function commonly used in embedded log printing. This macro printing function can display the file, number of lines, function name and other information you need. In addition, it should be noted that in the macro definition, try to use the do while(0) structure to contain the content. If you use curly braces {}, there will often be some errors. For example, I change the above code to the form of small faces contained in curly braces:

#define DBG_PRT(fmt, args...)\
{\
    printf(COLOR_RED"file:%s line:%s", __FILE__, __LINE__);\
    printf(fmt, ##args);\
}
if (1)
  DGB_PRT("hello world"); 
Expanded as:
if (1)
{
  printf(COLOR_RED"file:%s line:%s", __FILE__, __LINE__);printf(args);
};-->There will be one here; No, there will be grammatical errors

above DGB_PRT(fmt, args...)In the definition“..."Symbols represent variable parameters, args...The expression of is used in subsequent use
Can use args The identifier represents the variable parameter list, which is then used directly in the subsequent macro definition args Just represent the variable parameter list.
We're looking at identifiers args Preceded by macro connector ##,The advantage of this is that when the variable parameter list is not empty,## The function of is to connect fmt,And variable parameter list,
The parameters are separated by commas, and the macro can be used normally; When the variable parameter list is empty,## Another special use is to delete the comma after the fixed parameter fmt,
In this way, the macro can be used normally.

Two other ways to write variable parameter macros

First, use__ VA_ARGS__ Represents a list of variable parameters

#define DBG_PRT(fmt, ...)\
do\
{\ printf(COLOR_RED
"file:%s line:%s", __FILE__, __LINE__);\ printf(fmt, ##__VA_ARGS__);\ }while(0)

The second way of writing is relatively simple. It directly lists the variable parameters It is connected with fmt identifier, so that the fmt identifier can be directly used in subsequent use. This identifier contains both formatted string and variable parameter list. At the same time, it can deal with the case that the parameter is empty, because the variable parameter list and fmt are connected together. When the variable parameter list is empty, the content represented by the last fmt is only formatted string.

#define DBG_PRT(fmt...)\
do\
{\
    printf(COLOR_RED"file:%s line:%s", __FILE__, __LINE__);\
    printf(fmt);\
}while(0)

In addition, record the usage of # and ## (refer to https://blog.csdn.net/baidu_33850454/article/details/79363033 )

Use # to change the macro parameter into a string -- the stringing operator

Use ## to fit two macro parameters together -- the character concatenation operator

General usage

#include<cstdio>
#include<climits>
using namespace std;
#define STR(s)     #s
#define CONS(a,b)  int(a##e##b)
int main()
{
   printf(STR(vck));           // Output string"vck"
   printf("%d\n", CONS(2,3));  // 2e3 output:2000
   return 0;
}

Note: when the macro parameter is another macro, it should be noted that where there is' # 'or' ## 'in the macro definition, the macro parameter will not be expanded
That is, only the current macro takes effect, and the macro in the parameter! no meeting! Sheng! Effective!!!!

#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 #
printf("%s\n", CONS(A, A));                // compile error --- int(AeA)

After expansion:

printf("int max: %s\n","INT_MAX");
printf("%s\n", int(AeA));

Due to A and INT_MAX is A macro and is used as A parameter of macros CONS and STR, and both macros CONS and STR contain # or ## symbols, so A and INT_MAX cannot be dereferenced. Lead to unexpected situations.

The solution to this problem is simple Add one more layer of intermediate conversion macro The purpose of adding this layer of macro is to expand all macro parameters in this layer, so the correct macro parameters can be obtained by converting the macro (_STR) in the macro

#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));
//Output: int Max: 0x7fffff
//STR(INT_MAX) --> _STR(0x7fffffff)
Then it is converted into a string; printf("%d\n", CONS(A, A));
//Output: 200
//CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))

 

Posted by benwestgarth on Tue, 10 May 2022 03:02:28 +0300