7

Imagine I want to #define a macro such that it is equal to the current value of another macro (if such a concept exists).

For example:

#include "def_a.h"  // defines macro A
#define B A

This defines B to be A. If A later changes definition (i.e., through a redefinition) the value of B also changes (because B expands to A at the point of use, which further expands to the new value of A).

What I'd like is some way to "bake in" the value of A into B so that B just expands to the value of A, not A itself.

For example:

#define A first
#define B BAKE_IN(A)
#undef A
#define A second
#define C BAKE_IN(A)
#undef A
#define A third

// here I want B to expand to first, and C to expand to second

Of course BAKE_IN is not a real thing, but I'm wondering if there is some way to achieve this effect.

Now, I didn't really say what should happen if A itself is defined in terms of other macros, but I'm OK both with "one level of expansion" (i.e., B gets the value of A is expanded, so further macros remain) and also "full expansion" (i.e., A is fully expanded, recursively, as it would be at a point of use).

11
  • 1
    Ok, I was not sure ... does someone know how to mark a question as duplicate without closing it? Commented Feb 7, 2017 at 17:48
  • 1
    As far as I know, those are mutually exclusive. If a question is marked as duplicate, it gets closed with the little banner at the top directing you to the old question. Commented Feb 7, 2017 at 17:51
  • 1
    @Sabrina - I want to #include a header file with specific macros defined/not-defined and then "capture" the value of a macro that this header file defines. Later, the macro that I captured from may change value, but I want the original value. Commented Feb 7, 2017 at 18:23
  • 1
    @Sabrina: That is no way related to C# Commented Feb 7, 2017 at 18:29
  • 1
    @beeonrope: basically, this isn't possible with the preprocessor and even if it were, it wouldn't help with your use case. I put a suggestion about the assert use case as an answer to your other question; in this context, I'm going to stick with the answer I provided: you can freeze a macro only if it's value is an integer, and only with the black pp magic of boost-pp. Commented Feb 7, 2017 at 23:26

2 Answers 2

2

I don't think there is a clean solution. The closest thing that I found is to preserve "stringified" values within char arrays:

#include <stdio.h>

#define BAKE_IN(X, id) BAKE_IN_REAL(X ## _, X, id)
#define BAKE_IN_REAL(X, Y, id) static const char X ## id[] = #Y;
#define BAKE_OUT(X, id) X ## _ ## id

#define A first
BAKE_IN(A, 1)
#define B BAKE_OUT(A, 1)
#undef A

#define A second
BAKE_IN(A, 2)
#define C BAKE_OUT(A, 2)
#undef A

int main(void)
{
    printf("%s\n", B); // prints "first"
    printf("%s\n", C); // prints "second"
    return 0;
}

The idea is that BAKE_IN macro declares object named as e.g. A_1, which holds the current expansion of A.

There are two major limitations:

  • Every pair of BAKE_IN and BAKE_OUT needs unique id
  • The expansion is only available in "stringified" form
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! This is quite useful when you need a string version of the macro, which is actually the case for some type of diagnostics, so I'll probably use this in the future. I accepted the other answer in this case because it was more directly applicable (since I definitely don't need a stringified form for my use case), but this is a good contribution.
1

Macros are never replaced in the body of a #define directive, so there is no way to define a macro as the current value of another macro, except for the limited case of macros whose value is a constant arithmetic expression.

In the latter case, you can use BOOST_PP_ASSIGN_SLOT from the Boost preprocessor library. (Although most of the Boost libraries are C++-specific, the Boost preprocessor library works for both C and C++, and has no dependency on any other Boost component.)

8 Comments

Your "exception" is none actually. And this is about C, not C++.
@olaf: the boost preprocessor library works in both C and C++.
@Olaf - does the underlying technique BOOST_PP_ASSIGN_SLOT uses work in C then, or are the preprocessor rules different?
@BeeOnRope: Boost is a C++ library. And it cannot change how cpp works.
@olaf: boost-pp is not a c++ library. It is true that it does not change how cpp works -- but it has lots of tricks to make it do things you might not expect are possible.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.