[Macro definition] - Get the number of parameters of the variable parameter macro

Function Description

Used to get how many arguments were actually passed to the variadic macro.

  • COUNT_ARGS(1, 2, 3), filled in 3 parameters, the return value is 3
  • COUNT_ARGS("Hello", 'a', 3.14, 4), filled in 4 parameters, the return value is 4
  • COUNT_ARGS(1), we filled in 1 parameter, and the return value is 1

accomplish

#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N
#define COUNT_ARGS(...) __COUNT_ARGS(, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
  1. The __COUNT_ARGS macro defines a macro with multiple parameters, where _0 to _20 are placeholder parameters, and N represents the number of parameters.
  2. The __COUNT_ARGS macro uses the feature of variable parameter macros, and converts the parameter sequence into a comma-separated parameter list through ##.
  3. The COUNT_ARGS macro defines a variadic macro that uses the __COUNT_ARGS macro to count the number of arguments.
  4. The COUNT_ARGS macro handles the case of no arguments by adding an empty argument (,) to avoid compilation errors.
  5. The COUNT_ARGS macro can accept up to 20 parameters, if more than 20 parameters, only the first 20 parameters will be counted.

...the role of

...is a variable parameter macro syntax, which means that any number of parameters can be accepted. In a macro definition, ...indicates the end of the list of parameters that can be used in the definition of the macro.

__VA_ARGS__the role of

  • __VA_ARGS__is a special macro that represents a placeholder for variable arguments. In a macro definition, __VA_ARGS__will be replaced by the actual parameters passed to the macro. It can be used to pass variable arguments to other macros or functions.

##__VA_ARGS__the role of

##__VA_ARGS__is a special syntax used in variadic macros. Its function is to remove the comma connector of variable parameters during macro expansion to avoid redundant commas. This is useful in some cases, especially when the macro's argument list is empty.

When we COUNT_ARGSpass no parameters to , __VA_ARGS__the value of is empty, , ##__VA_ARGS__and this part will be deleted. Here is the syntax using ##, when is an empty string, it will be deleted together __VA_ARGS__with the initial .,

analyze

#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N

This macro requires at least 22 parameters to be passed, and the return value is the first 22parameter.

If it exceeds the 22nd parameter, it will be digested by ... and return the 22nd parameter.

In fact, the essence of this macro is to use to occupy the place first 20, 19, ... 1, 0, and every time an additional parameter is added, the rightmost number will be squeezed out.

Add one parameter, 0 will be squeezed out, return the 22nd parameter is 1,
add two parameters, 0 and 1 will be squeezed out, return the 22nd parameter is 2 and
so on

COUNT_ARGS(2, 4, 5)

COUNT_ARGS(2, 4, 5) expands to

__COUNT_ARGS(, 2, 4, 5, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

Passed 25 parameters to __COUNT_ARGS, and then we will correspond to __COUNT_ARGSthe in :形参

The function of the __COUNT_ARGS macro is to return the 22nd parameter of the actual parameter. In fact, __COUNT_ARGS passed 25 parameters, so the macro only returns the 22nd parameter.3

No arguments COUNT_ARGS()

COUNT_ARGS() expands to become

__COUNT_ARGS(, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

There are 22 parameters passed to __COUNT_ARGS, and then the passed parameters are __COUNT_ARGSin one-to-one correspondence with the formal parameters in:
The function of the __COUNT_ARGS macro is to return the 22nd parameter of the actual parameter. Actually, __COUNT_ARGS passed 22 parameters, so this macro only returns the 22nd parameter 22 parameters are0

More than 22 parameters

Also note that the number of incoming parameters cannot exceed 22. If more than 22 parameters are passed in, this macro will return the parameter value of the 22nd parameter.

For example

COUNT_ARGS(c)

After macro expansion is

(, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 46, 76, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

Passed 44 parameters to __COUNT_ARGS, and then we will correspond to __COUNT_ARGSthe in :形参

The function of the __COUNT_ARGS macro is to return the 22nd parameter of the actual parameter. The actual __COUNT_ARGS passed 44 parameters, so the macro only returns the 22nd parameter.46

So when the number of parameters exceeds 22, no matter how many parameters there are, N always corresponds to the value of the 22nd parameter.

example

#include <stdio.h>

#define __COUNT_ARGS(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, N, ...) N
#define COUNT_ARGS(...) __COUNT_ARGS(, ##__VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

int main(int argc, char *argv[])
{
    
    
    int count1 = COUNT_ARGS();                                                                              // count1 = 0
    int count2 = COUNT_ARGS(1, 2, 3);                                                                       // count2 = 3
    int count3 = COUNT_ARGS(1, 2, 3, 4, 5, 6, 7);                                                           // count3 = 7
    int count4 = COUNT_ARGS("Hello", 'a', 3.14);                                                            // count4 = 3
    int count5 = COUNT_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);         // count5 = 20
    int count6 = COUNT_ARGS(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 46, 76); // count6 = 20

    printf("count1 = %d\n", count1);
    printf("count2 = %d\n", count2);
    printf("count3 = %d\n", count3);
    printf("count4 = %d\n", count4);
    printf("count5 = %d\n", count5);
    printf("count6 = %d\n", count6);

    return 0;
}

result print

count1 = 0
count2 = 3
count3 = 7
count4 = 3
count5 = 20
count6 = 46

Guess you like

Origin blog.csdn.net/tyustli/article/details/131969837