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
Variable Assignment in an "If" Condition
Why Did Microsoft Abandon Long Double Data Type
When Is an Object "Out of Scope"
Lifetime of a String Literal Returned by a Function
Difference Between Pointer to a Reference and Reference to a Pointer
Should I Worry About the Alignment During Pointer Casting
Convert a String to a Date in C++
How to Get the Type of a Variable
(How) How to Count the Items in an Enum
How to Use Setprecision in C++
No Match for 'Operator<<' in 'Std::Operator
Are Vectors Passed to Functions by Value or by Reference in C++