Reputation: 1891
I want to generate the name of an AVR interrupt vector with the C preprocessor and with a given interface name. So I have this configuration file (Config.h
) which is included to another header file.
#define INTERFACE C, 0
#define BAUD 19200
and this macro to get the ISR name
#include "Config.h"
#define ISR_NAME(Name, Vector) USART ## C0 ## _ ## Vector ## _vect
This macro is used in my code
#include "Config.h"
ISR(ISR_NAME(INTERFACE, RXC))
{
// Some stuff
}
and it works pretty fine. But the name of the interface should set according to the given INTERFACE
and for this I change the macro ISR_NAME
to the following
#include "Config.h"
#define CATENATE(Prefix, Index) Prefix ## Index
#define ISR_NAME(Name, Vector) USART ## CATENATE(Name) ## _ ## Vector ## _vect
With using the macro like before
#include "Config.h"
ISR(ISR_NAME(INTERFACE, RXC))
{
// Some code
}
This solution produce a loot of warnings and errors
Severity Code Description Project File Line
Message in expansion of macro 'ISR_NAME' ...
Message in expansion of macro 'ISR_NAME' ...
Message in expansion of macro 'ISR_NAME' ...
Message in expansion of macro 'INTERFACE' ...
Message in expansion of macro 'INTERFACE' ...
Error expected ')' before numeric constant File ...
Error expected ')' before numeric constant File ...
Error recipe for target 'File.o' failed File ...
Error pasting ")" and "_" does not give a valid preprocessing token ...
What is going wrong here? Why does this extra macro produces this errors?
Upvotes: 0
Views: 246
Reputation: 241771
The problem is "clearly" described by this error message
Error pasting ")" and "_" does not give a valid preprocessing token
which applies to this expansion:
USART ## CATENATE(Name) ## _ ## Vector ## _vect
("Clearly" here is a bit of a joke. The error is clearly described, but you need to sift through a lot of chaff to find the informative error message.)
When you look at that line, you see CATENATE(Name)
being concatenated to _
. But that's not what the preprocessor sees, because the token pasting operator ##
is applied before rescanning the replacement text for further macro expansions. What the preprocessor sees is ) ## _
, which, as it points out, does not produce a legal token. (The preprocessor also joined USART ## CATENATE
producing the legal but undefined token USARTCATENATE
, which it didn't bother to warn you about. But that presumably has other consequences which produce other errors.)
If you want to token paste the result of a macro expansion, whether it is a simple macro expansion or a function-like macro expansion, you need to use an indirect token-pasting macro, like your CATENATE
:
#define ISR_NAME(Name, Vector) \
CATENATE(USART, CATENATE(CATENATE(Name), CATENATE(_, CATENATE(Vector, _vect))))
Of course, that will fully macro-expand both Name
and Vector
, which might not be exactly what you wanted. To get what you want, you need to be clear about the order of macro expansion for function-like macros which use the #
or ##
operators:
Macro parameters are substituted with the arguments from the call, except for those parameters which appear as the argument to an #
or ##
operator. The arguments are fully-expanded before this substitution.
The ##
and #
operators are applied.
#
must be followed by a macro parameter name; the corresponding argument is transformed into a string literal without any macro expansions being performed on the argument.##
, that parameter is substituted by its corresponding argument, again without any macro expansions being performed. (If a substituted parameter corresponds to an empty argument, then a special empty placeholder is inserted.) Then every occurrence of two tokens (or placeholders) separated by ##
is replaced with a new token representing the concatenation of the two original tokens.Finally, the resulting substitution text is rescanned for macro expansions.
Function-like macro arguments are identified during the (re-)scan, which is why CATENATE(INTERFACE)
works as expected (except on non-compliant C preprocessors, such as historic MSVC implementations) inside a macro definition, but not at the top level.
Upvotes: 1