Print MACro Values Without Knowing the Amount of MACros

Print macro values without knowing the amount of macros

First of all, we know we can count on Boost.Preprocessor for our looping needs. However, the generated code must work on its own. Unfortunately, #ifdef cannot work as a result of macro expansion, so there's no way to generate the code in your question. Are we toasted?

Not yet! We can take advantage of the fact that your macros are all either nonexistent or a string literal. Consider the following:

using StrPtr = char const *;
StrPtr probe(StrPtr(MACRO1));

We're taking advantage of our old friend the most vexing parse here. The second line can be interpreted in two ways depending on whether MACRO1 is defined. Without it, it is equivalent to:

char const *probe(char const *MACRO1);

... which is a function declaration where MACRO1 is the name of the parameter. But, when MACRO1 is defined to be "B", it becomes equivalent to:

char const *probe = (char const *) "B";

... which is a variable initialized to point at "B". We can then switch on the type of what we just produced to see if a substitution occured:

if(!std::is_function<decltype(probe)>::value)
std::cout << "MACRO1 " << probe << '\n';

We could make use of if constexpr here, but std::cout can output a function pointer (it converts it to bool) so the dead branch is valid, and the compiler is clever enough to completely optimize it out.

Finally, we come back to Boost.Preprocessor to generate all that stuff for us:

#define PRINT_IF_DEFINED(z, n, data) \
{ \
StrPtr probe(StrPtr(BOOST_PP_CAT(MACRO, n))); \
if(!std::is_function<decltype(probe)>::value) \
std::cout << "MACRO" BOOST_PP_STRINGIZE(n) " " << probe << '\n'; \
}

#define PRINT_MACROS(num) \
do { \
using StrPtr = char const *; \
BOOST_PP_REPEAT(num, PRINT_IF_DEFINED, ~) \
} while(false)

... voilà!

See it live on Coliru

Note: the Coliru snippet includes warning disablers for GCC and Clang, which warn against our poor pal the most vexing parse :(

Printing name and value of a macro

As long as you are willing to put up with the fact that SOMESTRING=SOMESTRING indicates that SOMESTRING has not been defined (view it as the token has not been redefined!?!), then the following should do:

#include <stdio.h>

#define STR(x) #x
#define SHOW_DEFINE(x) printf("%s=%s\n", #x, STR(x))

#define CHARLIE -6
#define FRED 1
#define HARRY FRED
#define NORBERT ON_HOLIDAY
#define WALLY

int main()
{
SHOW_DEFINE(BERT);
SHOW_DEFINE(CHARLIE);
SHOW_DEFINE(FRED);
SHOW_DEFINE(HARRY);
SHOW_DEFINE(NORBERT);
SHOW_DEFINE(WALLY);

return 0;
}

The output is:

BERT=BERT
CHARLIE=-6
FRED=1
HARRY=1
NORBERT=ON_HOLIDAY
WALLY=

How do I show the value of a #define at compile-time?

I know that this is a long time after the original query, but this may still be useful.

This can be done in GCC using the stringify operator "#", but it requires two additional stages to be defined first.

#define XSTR(x) STR(x)
#define STR(x) #x

The value of a macro can then be displayed with:

#pragma message "The value of ABC: " XSTR(ABC)

See: 3.4 Stringification in the gcc online documentation.

How it works:

The preprocessor understands quoted strings and handles them differently from normal text. String concatenation is an example of this special treatment. The message pragma requires an argument that is a quoted string. When there is more than one component to the argument then they must all be strings so that string concatenation can be applied. The preprocessor can never assume that an unquoted string should be treated as if it were quoted. If it did then:

#define ABC 123
int n = ABC;

would not compile.

Now consider:

#define ABC abc
#pragma message "The value of ABC is: " ABC

which is equivalent to

#pragma message "The value of ABC is: " abc

This causes a preprocessor warning because abc (unquoted) cannot be concatenated with the preceding string.

Now consider the preprocessor stringize (Which was once called stringification, the links in the documentation have been changed to reflect the revised terminology. (Both terms, incidentally, are equally detestable. The correct term is, of course, stringifaction. Be ready to update your links.)) operator. This acts only on the arguments of a macro and replaces the unexpanded argument with the argument enclosed in double quotes. Thus:

#define STR(x) #x
char *s1 = "abc";
char *s2 = STR(abc);

will assign identical values to s1 and s2. If you run gcc -E you can see this in the output. Perhaps STR would be better named something like ENQUOTE.

This solves the problem of putting quotes around an unquoted item, the problem now is that, if the argument is a macro, the macro will not be expanded. This is why the second macro is needed. XSTR expands its argument, then calls STR to put the expanded value into quotes.

Print a #define macro using std::cout

"_TEST_" is a string literal and not a macro. So no macro replacement will be done due to "_TEST_". To achieve your expected output you need to remove the surrounding double quotes and also change the macro to as shown below

//-------------vvvvvv--->double quotes added here
#define _TEST_ "test"
#include <iostream>

int main()
{
//-------------------vvvvvv---------------> not withing quotes
std::cout << _TEST_ << std::endl;
}

The output of the above modified program is:

test

Demo

Explanation

In the modified program, the macro _TEST_ stands for the string literal "test". And thus when we use that macro in the statement std::cout << _TEST_ << std::endl;, it will be replaced by the string literal, producing the expected output.

#define macro doesn't print variable

The problem isn't in the macro. It is in how you use it. Essentially, your usage requires you to use PRINT with a format string, which must be a string literal that describes what to do with the subsequent arguments.

For example, try

PRINT("x = %d y = %d\n", x, y);

where x and y are variables of type int.

C Macros that invoke different Macros according to the argument values

This code does what you seem to request:

#define REG_WIDGET_ADDR 0x1000
#define REG_WIDGET_IS_BYTE 1

#define REG_GADGET_ADDR 0x1002
#define REG_GADGET_IS_BYTE 0

// These two macros provide the requested expansions for word and byte access.
#define REG_ACCESS_T0(a) *(a)
#define REG_ACCESS_T1(a) __byte(*(a), 0)

// This macro uses argument b to select between the two macros above.
#define REG_ACCESS3(a, b) REG_ACCESS_T##b(a)

// This macro is needed to let argument b be replaced.
#define REG_ACCESS2(a, b) REG_ACCESS3(a, b)

// This macro uses x to get the corresponding address and is-byte macros.
#define REG_ACCESS(x) REG_ACCESS2(REG_##x##_ADDR, REG_##x##_IS_BYTE)

REG_ACCESS(WIDGET) = 0x0A;
REG_ACCESS(GADGET) = 0xCAFE;

The results of macro replacement are:

__byte(*(0x1000), 0) = 0x0A;
*(0x1002) = 0xCAFE;


Related Topics



Leave a reply



Submit