Preprocessor definition duplication

macro argument reuse possible side effects
defined preprocessor

I have two libraries and unfortunately they define two identical preprocessor definitions (which I need to use):

lib1.h

#define MYINT 1

lib2.h

#define MYINT 2

In my program I need to use both of them:

#include <Lib1.h>
#include <lib2.h>
...
int myint = MYINT;

And here I have error that MYINT can't be resolved.

How can I solve that when I cannot modify the lib files?

You might #undef MYINT before to include the header as workaround.

#undef MYINT
#include <Lib1.h>
const int myint_lib1 = MYINT; // 1

#undef MYINT
#include <lib2.h>
const int myint_lib2 = MYINT; // 2

Preprocessor, is a program that processes its input data to produce output that is used as input to another program. A common example from computer programming is the processing performed on source code before the next step of compilation. a program that performs some type of processing, as organization of data or preliminary computation, in advance of another program that will perform most of the processing.

Get the MYINT value of the first library before the second one replaces it.

#include <Lib1.h>
int myInt1 = MYINT;
#undef MYINT
#include <lib2.h>
int myInt2 = MYINT;
#undef MYINT

Of course, that doesn't work if MYINT is something dynamic and you need to keep its actual content around.

Edited by handy999: no semicolon at the end of preprocessor statements.

The C Preprocessor: 1. The C Preprocessor, implementations, it is a separate program invoked by the compiler as the first part of translation. a program that performs some type of processing, as organization of data or preliminary computation, in advance of another program that will perform most of the processing Most material © 2005, 1997, 1991 by Penguin Random House LLC. Modified entries © 2019 by Penguin Random House LLC and HarperCollins Publishers Ltd

With no preprocessor tricks:

lib1_handler.h

extern int lib1_handler_myint;
// or
int lib1_handler_myint_f();

lib1_handler.c

#include <Lib1.h>

int lib1_handler_myint = MYINT;
// or
int lib1_handler_myint_f() { return MYINT; }

lib2_handler.h

extern int lib2_handler_myint;
// or
int lib1_handler_myint_f();

lib2_handler.c

#include <Lib2.h>

int lib2_handler_myint = MYINT;
// or
int lib2_handler_myint_f() { return MYINT; }

main.c

#include "lib1_handler.h"
#include "lib2_handler.h"

int void () {
  return lib1_handler_myint || lib2_handler_myint_f();
}

C preprocessor, has been there from the earliest times of programming languages. Duplication is a type of mutation that involves the production of one or more copies of a gene or region of a chromosome. Gene and chromosome duplications occur in all organisms, though they are especially prominent among plants. Gene duplication is an important mechanism by which evolution occurs.

The approach I would take is to derive from each of the include files an extended version of the include files which will provide the MYINT through a different mechanism outside of the include files themselves.

So create an include file from lib1.h named lib1_ext.h containing the following lines:

#if !defined(MYLIB1_EXT_H_INCLUDED)
#define MYLIB1_EXT_H_INCLUDED
// ensure that MYINT is not defined no matter what order the include files are used
#undef MYINT
#include "lib1.h"
const int myInt_lib1 = MYINT;  // make a copy of the value of MYINT if it is needed
// make sure MYINT is undefined to allow the compiler to catch any dependencies on it
#undef MYINT
#endif

and similarly for lib2.h create lib2_ext.h as in:

#if !defined(MYLIB2_EXT_H_INCLUDED)
#define MYLIB2_EXT_H_INCLUDED
// ensure that MYINT is not defined no matter what order the include files are used
#undef MYINT
#include "lib2.h"
const int myInt_lib2 = MYINT;  // make a copy of the value of MYINT if it is needed
// make sure MYINT is undefined to allow the compiler to catch any dependencies on it
#undef MYINT
#endif

now when using any of the functionality of the library use the respective copy of the MYINT value, myInt_lib1 when using lib1.h functionality and/or myInt_lib2 when using lib2.h functionality. However if MYINT is only used with the library header file itself and is not needed anywhere to actually use the library then you can just discard that statement.

See as well Can I redefine a C++ macro then define it back? which shows how to save and restore a macro definition with some vendors' compilers and the pragma directive. It doesn't look like that is really applicable with your posting however.

That posting also has an answer which describes the basics of macro expansion and why the const int myInt_lib1 = MYINT; is needed to save the value of MYINT rather than using the Preprocessor as in #define MYINT_LIB1 MYINT to save the value of MYINT. The Preprocessor delays the expansion of a macro as long as possible and the result is that trying to use a Preprocessor macro as in #define MYINT_LIB1 MYINT to save the value of MYINT doesn't work once MYINT is undefined using the #undef directive. When the Preprocessor first replaces the text MYINT_LIB1 with the text MYINT and then does a rescan, since MYINT is now undefined, the text MYINT remains and the result is a compiler error if you are lucky.

One thing to consider with this work around

This work around assumes that all that is needed is the numerical value of MYINT which is treated as an int constant value. So it assumes that the places where MYINT is used are places where a const int can also be used.

This means that any kind of token pasting, #if test or other Preprocessor action that involves treating the text which MYINT is defined as text that can be used by the Preprocessor for other macro operations is not going to work properly outside of the places where the lib.h or lib2.h are included and processed by the Preprocessor.

It also means that you can not specify a compiler option to declare MYINT as a part of conditional compilation since the macro created by the compiler option is going to be ignored and eliminated by this work around.

So any dependency that the source generated by the Preprocessor has on MYINT as a text macro outside of each of the include files will cause the compile to break.

An example of a possible dependency would be a macro within lib1.h which uses MYINT to create an additional, unseen argument to a function as in:

int funcStuff (int a, struct b *pBthing);

#define FUNCSTUFF (pBthing)  funcStuff(MYINT, (pBthing))

with the expectation that anybody using the library would use FUNCSTUFF(&bThing); rather than funcStuff (MYINT, &bThing);. To make this work you would need to either use the function funcStuff() directly as in funcStuff(myInt_lib1, &bThing); or make your own version of the FUNCSTUFF() macro that uses myInt_lib1 rather than MYINT.

Case for Preprocessing Capabilities in the Java Language, 4 Duplication of Side Effects. Many C programs define a macro min , for “​minimum”, like this: #define min(X, Y)  Preprocess definition is - to do preliminary processing of (something, such as data).

Duplication of Side Effects (The C Preprocessor), The C preprocessor is a macro processor that is used automatically by the C to define a "minimum" macro in GNU C. See section Duplication of Side Effects,  Preprocess definition, a systematic series of actions directed to some end: to devise a process for homogenizing milk. See more.

The C Preprocessor - The C Preprocessor, preprocessing macroS, 459 #define, preprocessing directive,452 See also preprocessing directives preventing duplication of Box class definition with, 674  C - Preprocessors - The C Preprocessor is not a part of the compiler, but is a separate step in the compilation process. In simple terms, a C Preprocessor is just a text substituti

Ivor Horton's Beginning ANSI C++: The Complete Language, Definition of Duplicated Zones In this manuscript, we define a duplication as an identical Preprocessing All documents generated in the hospital comprised  In the Preprocessor Definitions dialog box, add (one per line), modify, or delete one or more definitions. Choose OK to save your changes. You don't need to include the '/D' option prefix on the definitions you specify here. In the property page, definitions are separated by semicolons (;). To set this compiler option programmatically

Comments
  • You've not stated what you want MYINT to ultimately be at this stage, you can #ifdef MYINT #undef MYINT etc..
  • The preprocessor is going to replace the macro with the value, which one does it have to choose?
  • Which version of the macro do you need?
  • Do you have the luxury of targetting only one operating system? If so, which one? I'm thinking in terms of linking the libraries dynamically.
  • @Bathsheba: How would dynamic linking resolve collisions in preprocessor identifiers?
  • Use constexpr if possible.
  • BTW, first #undef isn't required.
  • I would add #undef MYINT after each to avoid warnings and misuse
  • Good suggestion, I added it to the answer.
  • The two libs already were identified to have a naming conflict. Including them into one translation unit seems very optimistic to me.
  • You're right. The root problem is that two libs are using macro names that aren't specific enough not to create a naming conflict like this. Ideally I'd try to tackle the "cannot modify the lib" part.