Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Suppress C Macro Variable Substitution

I have this bit of code (part of an interpreter for a garbage-collected Forth system, actually):

#define PRIMITIVE(name) \
    do \
    { \
        VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); \
        entry->code = name; \
        entry->name = cstr_to_pstr(#name); \
        entry->prev = latest_vocab_entry; \
        latest_vocab_entry = entry; \
    } \ 
    while (false)

PRIMITIVE(dup);
PRIMITIVE(drop);
PRIMITIVE(swap);
// and a lot more

but there's a problem: in the line

entry->name = cstr_to_pstr(#name);

the name field is substituted for dup, drop, swap, and the rest. I want the field name to not be substituted.

So, is there any way to solve this, other than simply renaming the macro argument?

For an answer, please explain if there is, in general, a way to suppress the substitution of a macro argument name in the macro body. Don't answer "just do it this way" (please).

like image 356
feralin Avatar asked Aug 11 '13 01:08

feralin


People also ask

What to use instead of #define in C?

Use const Instead of #define to Define Constants.

What is macro substitution in C?

Macro substitution is a mechanism that provides a string substitution. It can be achieved through "#deifne". It is used to replace the first part with the second part of the macro definition, before the execution of the program. The first object may be a function type or an object.

What is __ Va_opt __?

__VA_OPT__ is a new feature of variadic macros in C++20. It lets you optionally insert tokens depending on if a variadic macro is invoked with additional arguments. An example usage is comma elision in a standardized manner.

What does ## do in a macro?

The double-number-sign or token-pasting operator (##), which is sometimes called the merging or combining operator, is used in both object-like and function-like macros. It permits separate tokens to be joined into a single token, and therefore, can't be the first or last token in the macro definition.


1 Answers

You can define a different macro to expand to name, like this:

#define Name name

and change the name field in the PRIMITIVE macro to use the new macro, like this:

#define PRIMITIVE(name) \
    do \
    { \
        VocabEntry* entry = (VocabEntry*)gc_alloc(sizeof(VocabEntry)); \
        entry->code = name; \
        entry->Name = cstr_to_pstr(#name); \
        entry->prev = latest_vocab_entry; \
        latest_vocab_entry = entry; \
    } \ 
    while (false)

Other than using something different from the parameter name in the macro body or changing the parameter name, there is no other way to do this in the C language. Per C 2011 (N1570) 6.10.3.1 1, when a function-like macro is recognized, parameter names are immediately substituted except when # or ## is present, and there no other exceptions:

After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place. A parameter in the replacement list, unless preceded by a # or ## preprocessing token or followed by a ## preprocessing token (see below), is replaced by the corresponding argument after all macros contained therein have been expanded.

The # token changes the parameter name to a string, which is no use in this situation. The ## token expands the parameter name and pastes it together with an adjacent token, which is also no use in this situation.

like image 71
Eric Postpischil Avatar answered Sep 17 '22 17:09

Eric Postpischil