4

So I have this 'check' macro which takes two arguments :

#define check(reg, n) ((reg >> n) & 1U)

And I have this argument list :

#define TEST_ARGS 10, 1

The code :

check(TEST_ARGS);

Expected expansion :

((10 >> 1) & 1U)

Real expansion :

((10, 1 >> ) & 1U)

How do I define multiple arguments for "check" macro to get expected results?

Many Thanks.

3 Answers 3

3

In top-level (not macro-replaced) input, macro invocations argument lists are parsed immediately, before the arguments are macro expanded. (This must be the case, because macro arguments used with # and ## macro operators are not expanded, and that's not known until the replacement body is examined.)

However, parameters in the replacement body are replaced with the respective arguments (which will have been macro-expanded if the parameter is not used with # or ##) before the replacement body is scanned for macros.

So you can achieve the effect you want by adding a level of indirection. However, you probably want to use a varargs macro, in case the invoker puts in an explicit comma:

#define CHECK(...) CHECK_(__VA_ARGS__)
#define CHECK_(reg, n) ((reg >> n) & 1U)

#define TEST_ARGS 10, 1
CHECK(TEST_ARGS)

Test:

$ $ gcc -x c -E - <<<'#define CHECK(...) CHECK_(__VA_ARGS__)
> #define CHECK_(reg, n) ((reg >> n) & 1U)
> 
> #define TEST_ARGS 10, 1
> CHECK(TEST_ARGS)'
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"




((10 >> 1) & 1U)
Sign up to request clarification or add additional context in comments.

Comments

2

Briefly, the issue is related to TEST_ARGS being treated as the first argument of the check() macro, and somehow an empty argument was imputed as the second argument on your compiler. (on all the compilers I tried, if the second argument is missing, the compiler will generate an error).


You need a level of indirection to allow your macro TEST_ARGS to expand before being passed to check().

For example:

#define check2(...) check(__VA_ARGS__)

Then, use check2(TEST_ARGS).


For MSVC, I have to do something a little more convoluted:

#define V_(...) __VA_ARGS__
#define I_(M,...) V_(M(__VA_ARGS__))
#define check2(...) I_(check, __VA_ARGS__)

1 Comment

This was helpful. I was dumb and running into a similar problem that 10,1 was being evaluated as a single token, not two arguments.
0

Preprocessor does the textual replace (actually it replaces tokens). So if

#define check(reg, n) ((reg >> n) & 1U)
#define TEST_ARGS 10, 1

then

check(TEST_ARGS);

is preprocessed as:

check(10, 1,);  

Where the first argument is the complete token 10,1 and the second one is empty

2 Comments

Possible to make it "check(10, 1);" ?
@malidu What for?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.