Tokubara
Tokubara

Reputation: 470

nested macro with __VA_ARGS__ does not expand

To get number of __VA__ARGS__, I read this answer and it works. But I feel that PP_NARG_ is redundant, and I see no reason why PP_RSEQ_N is a macro function. So I modify the code as below

#include <assert.h>
#define PP_RSEQ_N \
         63,62,61,60,                   \
         59,58,57,56,55,54,53,52,51,50, \
         49,48,47,46,45,44,43,42,41,40, \
         39,38,37,36,35,34,33,32,31,30, \
         29,28,27,26,25,24,23,22,21,20, \
         19,18,17,16,15,14,13,12,11,10, \
         9,8,7,6,5,4,3,2,1,0
#define PP_NARG(...) \
         PP_ARG_N(__VA_ARGS__,PP_RSEQ_N)
#define PP_ARG_N( \
          _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
         _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
         _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
         _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
         _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
         _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
         _61,_62,_63,N,...) N

/* Some test cases */

int main() {
  assert(PP_NARG(1,2,"yes",!)==4);
}

I get errors and notes.

main.c:24:33: error: macro "PP_ARG_N" requires 65 arguments, but only 5 given
   assert(PP_NARG(1,2,"yes",!)==4);
                                 ^

It seems that in PP_NARG, PP_RSEQ_N is not expanded. But why? I know that with # and ##, macro will not be expanded, but this is not the case.

Also I want to know why PP_NARG_ is necessary in this answer , and why PP_RSEQ_N is a macro function, not a normal macro(no arguments)?

Upvotes: 0

Views: 279

Answers (1)

rici
rici

Reputation: 241671

The essential nature of macro calls is that macro arguments are not expanded in the macro call. The precise procedure is specified in the standard at §6.10.3.1.

  1. After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place.

So the arguments to the macro are separated by the commas actually present in the token stream at that point, regardless of what the substituted argument might look like.

Once the arguments are collected, the uses of the macro parameters in the macro body are replaced with the arguments. In most cases, the arguments are expanded at this point, but (as you note) if the parameter is used as part of a # or ## expression, the argument is not macro-substituted for that use. Also, there is no requirement that a parameter be used at all in the macro body, so in such a case there will be no need to expand the argument at all.

Once the macro parameters have been replaced with the corresponding arguments and the # and ## operators are evaluated, the resulting token stream is passed back through the macro processor. It's during this rescan that any macros used in the body of the macro will be expanded.

Now, the author of PP_NARG actually wanted to construct a macro call consisting of the original varargs arguments to PP_NARG followed by the expansion of PP_RSEQ_N. Since the expansion of the macro argument PP_RSEQ_N won't take place until the expansion of the macro call it appears in, it's necessary to introduce an extra level of macro expansion; the PP_NARG_ macro is used to construct the call to PP_NARG. (You could avoid this by not using PP_RSEQ_N at all, instead putting the countdown directly in the call to PP_NARG. But there are abundant reasons to avoid this solution; it's cleaner to add the extra level of macro substitution.)

The usual reason to define a macro like PP_RSEQ_N as a function-like macro without arguments instead of a simple macro is to be able to pass around the name of the macro without it being expanded. That doesn't seem to be the case in this snippet, but it might be present elsewhere in the code from which the snippet was extracted.

Upvotes: 1

Related Questions