How to Redefine a C++ MACro Then Define It Back

Can I redefine a C++ macro then define it back?

As greyfade pointed out, your ___T___ trick doesn't work because the preprocessor is a pretty simple creature. An alternative approach is to use pragma directives:

 // juice includes here
#pragma push_macro("T")
#undef T
// include boost headers here
#pragma pop_macro("T")

That should work in MSVC++ and GCC has added support for pop_macro and push_macro for compatibility with it. Technically it is implementation-dependent though, but I don't think there's a standard way of temporarily suppressing the definition.

How to redefine a C++ #define macro using information from the macro itself?

Macros in macro bodies are never expanded when the macro is defined -- only when the macro is used. That means that the definition of NEW_DEFINE is not "ABC" "DEF", it is exactly what appears on the #define line: FINAL_DEFINE "DEF".

So when you use FINAL_DEFINE, that gets expanded to NEW_DEFINE which then gets expanded to FINAL_DEFINE "DEF". At this point it will not recursively expand FINAL_DEFINE (as that would lead to an infinite loop) so no more expansion occurs.

C macro redefined

The C preprocessor does not allow overloading of macros based on the number of arguments -- you can only have a single macro of a given name. You can get around this problem in your case by using redundant parentheses in the declaration of myfree:

#define myfree(p) do { myfree(p); p = (void *)0xdeadbeef; } while (0)

void (myfree)(void *p)
{
if(p != NULL)
free(p);
}

myfree(p); // Wrapper around free().

afunc(arg, myfree); // Wrapper is used as a function argument!

Redefining macros with old contents / Making a file include counter

Is there a way to expand the macros when the macro is defined.

Yes. But beware... using this as a means of generating unique symbols may cause unexpected linker issues if your symbols have external linkage.

Overview

The key problem here is that macros are not variables. With variables, if I have x=3*3; y=x;, then I'm assigning the value of x to y. With macros, if I have #define PPX 3*3 #define PPY PPX, then I'm literally assigning PPX to PPY. If I then evaluate PPY, it expands to PPX, and then to 3*3 but only because PPX is currently defined as 3*3.

However, there is a way around this. The preprocessor can evaluate expressions; it just uses conditional directives to do so. But due to the fact that this can branch, we can define macros conditionally based on PPX's value (as opposed to its replacement list). For example:

#if (PPX)%10==9
# define PPX_DIGIT_0 9
#elif (PPX)%10==8
# define PPX_DIGIT_0 8
...

So whereas PPY critically relies on PPX being defined as 3*3 to expand to 3*3; since PPX_DIGIT_0 is literally defined as 9, PPX can be undefined, and PPX_DIGIT_0 will still expand to 9. Note also that the conditional played a role in reducing the expression; (3*3)%10 is just equal to 9, causing the 9 branch to be hit. That loses the expression per se, picking up just the evaluation... which we want.

That's the idea. In practice, this requires a fair amount of code; fortunately, boost's preprocessor library already has it done for you, so here are two approaches using boost:

Approach 1: Using Boost Slots

include_counter.h:

#include <boost/preprocessor/slot/slot.hpp>
#if !(INCLUDE_COUNT)
# define INCLUDE_COUNT 0
# define BOOST_PP_VALUE INCLUDE_COUNT
# include BOOST_PP_ASSIGN_SLOT(1)
# undef BOOST_PP_VALUE
# undef INCLUDE_COUNT
# define INCLUDE_COUNT BOOST_PP_SLOT(1)
#endif
#define BOOST_PP_VALUE 1+INCLUDE_COUNT
#include BOOST_PP_ASSIGN_SLOT(1)

Boost slots evaluate macros and store their results using special internal states. You get 5 slots (code above is using slot 1), so you can store 5 numbers. This solution just initializes the slot to 0 before incrementing on the first include, then essentially just increments.

Approach 2: Use Boost Counter

include_counter.h:

#if !(INCLUDE_COUNT)
# include <boost/preprocessor/slot/counter.hpp>
# define INCLUDE_COUNT BOOST_PP_COUNTER
#endif
#include BOOST_PP_UPDATE_COUNTER()

Same idea, though it "consumes" boost counter.

Both boost solutions take the approach I just described. There's also a boost increment macro; feel free to ignore that, since (a) you're evaluating anyway, and (b) boost increment is a bit whimpy (with its maximum limit of 256).

You can also roll your own solution. But when you're done, it's going to look similar to boost's solution anyway. (The advantage is, your new "slot" will be independent of boost counter and boost slots).

Extending a macro in C

It is provably impossible to change a macro in any way without rewriting it from scratch. In the standard 6.10.3, you have:

An identifier currently defined as an object-like macro shall not be redefined by another
#define preprocessing directive unless the second definition is an object-like macro
definition and the two replacement lists are identical. Likewise, an identifier currently
defined as a function-like macro shall not be redefined by another #define
preprocessing directive unless the second definition is a function-like macro definition
that has the same number and spelling of parameters, and the two replacement lists are
identical.

So, you either have that a macro will expand exactly according to its definition, or else you need to #undef it. If you #undef it, to redefine it you need to write it from scratch. The old definition will not be available at that point, even to help in defining the new version.

You can't "reach" the old definition through any sort of intermediary because the preprocessor acts on definitions active at the point of the invocation, not at the points where the macros involved were defined. So, if you define temp(x) like you did, it expands in the context of your new definition of mat, not the old one (not to mention that there needed to be an undef between the two definitions of mat(x) and the anti-recursion rules will stop macro expansion at mat(x) anyway).

In short, there is absolutely no way, according to the standard, to redefine a macro in a way that is based on its original definition. This is mathematically provable from the standard.

Is there any reason you don't just modify the original definitions of the macros to deal with each type you are interested in? Or use some modification of the naming scheme to indicate your own version (like append _o to indicate a macro that deals with more types but ultimately relies on the corresponding macro)? Or, better yet, modify the names of the original macros, so that you can redefine them but have the originals available?

Edit

Going by the comment below, here is one way to maybe achieve some of what OP desires. Its not perfect, but the C preprocessor does have limitations. Here is an example that converts objects into a modifiable string.

write this in the header where you define the macro in the first place:

#define get_length(x) get_length_help(x)
#define get_length_help(x) sizeof(#x)

#define to_string(x) _Generic( (x), \
int: sprintf( (char[get_length(INT_MAX)]){0}, "%d", x ), \
char: sprintf( (char[2]){0}, "%c", x ), \
to_string_1,
to_string_2,
// ...
)

// make sure all extra spots expand to nothing until used
#define to_string_1
#define to_string_2
// ...

// macro to test if an extension slot is used
// requires that extensions do not begin with '('
#define used(...) used_help2( (used_help1 __VA_ARGS__ ()), 0, 1, )
#define used_help1() ),(
#define used_help2(_1,_2,_3,...) _3

Write this in foo.c

typedef struct {
int x,
int y
} plot_point

// this part is important, all generic selections must be valid expressions
// for the other types as well
#define safe_plot_point(x) _Generic( x, plot_point: x, default: (plot_point){0,0} )

// this could define a comma delimited list of selection statements as well
#define to_string_foo \
plot_point: sprintf( \
(char[get_length((INT_MAX,INT_MAX))]){0}, \
"(%i,%i)", \
safe_plot_point(x).x, safe_plot_point(x).y \
)

// this is the only real complication for the user
#if used(to_string_1)
#undef to_string_1
#define to_string_1 to_string_foo
#elif used(to_string_2)
#undef to_string_2
#define to_string_2 to_string_foo
// ...
#else
_Static_assert( 0, "no to_string_#'s left!" );
#endif

So, you can get some degree of modifiability. Note that no macro could just perform the modification, as it is undefined behavior for a macro to expand into another preprocessing directives, and as stated above preprocessing directives are the only way to change the behavior of a macro. Macro invocations are simply blind to other invocations, they only see other definitions.

Also note that you could define any number of extension slots. You can define more slots than a given file checks for, and only add the extra lines (the #if's), if they are needed.

Is it possible to redefine a macro without the use of ‘undef’?

No macro is illegally redefined here. Some may be defined more than once with identical definitions, which is OK. It's non-identical definitions that constitute a problem.

The DLL itself is always built with SIDX_DLL_EXPORT defined by the project settings. Code that uses the DLL is built without this macro being defined.

The second header is a part of the DLL. It is always compiled with SIDX_DLL_EXPORT being defined. Thus the macros defined by it, if any, are always identical to those defined in the first header. Such identical redefinition does not constitute a problem.

How is value of macro getting change

Preprocessing is done before the actual C code compilation. It simply textually replaces the token NUM with token var.

So after the preprocessing your function is:

int main()
{
int var;
printf("write the value of var:\n");
scanf("%d", &var);

printf("The value of S is %d\n", var);
var = var + 1; //changing the value of variable 'var'
printf("New value of S is %d", var);
return 0;
}

This main function is being compiled. As you see the NUM has been replaced with var and the result is obvious.



Related Topics



Leave a reply



Submit