preprocessor: checking for clashing #define

I

iler.ml

I am writing code that uses two third-party libraries.
They both define same macro OP_ENCRYPT, and
luckily for me, they both define it to 0. (In one include,
it's '#define OP_ENCRYPT 0', in another include it's 0x0).
I cannot change contents of those two includes.

This generates comipler warning 'macro redefined'. It's easy
to suppress the warning with #ifdef. But I want to also
cross-check that those two macros have same value.
I am thinking about this:

#include <first-lib.h> // defines OP_ENCRYPT
#define FIRST_OP_ENCRYPT OP_ENCRYPT //(*1)
#undef OP_ENCRYPT
#include <second-lib.h> // defines OP_ENCRYPT again
#if OP_ENCRYPT != FIRST_OP_ENCRYPT // (*2)
#error definitions mismatch
#endif

The problem here is that he rhs of define (*1) is expanded at line
(*2) which is too late. As a result, this does not really check
two values. The condition will always be true even if one
..h defined OP_ENCRYPT to 0 and other .h defined OP_ENCRYPT to 1.

I cannot change contents of those two includes.
Is there better way to check equality of macros defined in
two different includes without changing the contents of includefiles ?

Thanks
Yakov Lerner
 
J

Joe Smith

I am writing code that uses two third-party libraries.
They both define same macro OP_ENCRYPT, and
luckily for me, they both define it to 0. (In one include,
it's '#define OP_ENCRYPT 0', in another include it's 0x0).
I cannot change contents of those two includes.

This generates comipler warning 'macro redefined'. It's easy
to suppress the warning with #ifdef. But I want to also
cross-check that those two macros have same value.
I am thinking about this:

#include <first-lib.h> // defines OP_ENCRYPT
#define FIRST_OP_ENCRYPT OP_ENCRYPT //(*1)
#undef OP_ENCRYPT
#include <second-lib.h> // defines OP_ENCRYPT again
#if OP_ENCRYPT != FIRST_OP_ENCRYPT // (*2)
#error definitions mismatch
#endif

The problem here is that he rhs of define (*1) is expanded at line
(*2) which is too late. As a result, this does not really check
two values. The condition will always be true even if one
.h defined OP_ENCRYPT to 0 and other .h defined OP_ENCRYPT to 1.

I cannot change contents of those two includes.
Is there better way to check equality of macros defined in
two different includes without changing the contents of includefiles ?

Have you drawn a picture of the logic? Joe
 
E

Eric Sosman

I am writing code that uses two third-party libraries.
They both define same macro OP_ENCRYPT, and
luckily for me, they both define it to 0. (In one include,
it's '#define OP_ENCRYPT 0', in another include it's 0x0).
I cannot change contents of those two includes.

This generates comipler warning 'macro redefined'. It's easy
to suppress the warning with #ifdef. But I want to also
cross-check that those two macros have same value.
I am thinking about this:

#include <first-lib.h> // defines OP_ENCRYPT
#define FIRST_OP_ENCRYPT OP_ENCRYPT //(*1)
#undef OP_ENCRYPT
#include <second-lib.h> // defines OP_ENCRYPT again
#if OP_ENCRYPT != FIRST_OP_ENCRYPT // (*2)
#error definitions mismatch
#endif

The problem here is that he rhs of define (*1) is expanded at line
(*2) which is too late. As a result, this does not really check
two values. The condition will always be true even if one
.h defined OP_ENCRYPT to 0 and other .h defined OP_ENCRYPT to 1.

I cannot change contents of those two includes.
Is there better way to check equality of macros defined in
two different includes without changing the contents of includefiles ?

If you know the intended values, you can check the
two definitions separately:

#define OP_SHOULD_BE 0
#include <first-lib.h>
#if OP_ENCRYPT != OP_SHOULD_BE
#error "first-lib.h is broken"
#endif
#undef OP_ENCRYPT
#include <second-lib.h>
#if OP_ENCRYPT != OP_SHOULD_BE
#error "second-lib.h is broken"
#endif

If you know the values are both positive and not too
large, you can use a dirty trick:

#include <first-lib.h>
char fake_array[OP_ENCRYPT];
#undef OP_ENCRYPT
#include <second-lib.h>
/* If the following provokes an error about inconsistent
* array size or redeclared identifier or some such, the
* headers disagree about OP_ENCRYPT:
*/
char fake_array[OP_ENCRYPT];

This trick could be made to work for zero values by adding
1, or for small negative values by adding N. Unfortunately,
it also creates the useless fake_array[] ...

A run-time check is fairly easy to write:

#include <assert.h>
#include <first-lib.h>
static int first_value(void) {
return OP_ENCRYPT;
}
#undef OP_ENCRYPT
#include <second-lib.h>
...
int main(void) {
assert (first_value() == OP_ENCRYPT);
...

Most compilers will generate very little extra code for this;
some will even optimize the whole thing away (if the headers
agree).

The best approach, though, is to avoid using both libraries
in the same piece of code: You are begging for trouble. Try to
organize your code in such a way that some modules use library
A and some uaw library B, but no modules use both libraries.
Remember, the next version of library A might introduce a new
#define that completely bollixes library B ...

Separating the libraries may be easier than you think; even
in extreme cases it can often be handled through a "glue" layer
that "translates" between the two libraries' symbologies.
 
I

iler.ml

If you know the intended values, you can check
the two definitions separately:

#define OP_SHOULD_BE 0
#include <first-lib.h>
#if OP_ENCRYPT != OP_SHOULD_BE
#error "first-lib.h is broken"
#endif
#undef OP_ENCRYPT
#include <second-lib.h>
#if OP_ENCRYPT != OP_SHOULD_BE
#error "second-lib.h is broken"
#endif

Nice. This is what I'm going to use.

Thanks
Yakov
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top