pre processor compare variables - c++

I have a file A.h and B.h.
FileA.h is:
#define AA1 1
#define BB2 2
#define CC3 3
FileB.h is:
#include <FileA.h>
#define AA 1
#define BB 2
#define CC 3
#if AA != FileA.AA1 //is this the way to call AA1 variable in FileA??
#error "Mismatch variable"
#endif
I want to have a compiler error when if the definein fileA.h does not match the value in file FileB.h. Therefore I added a #error.
How would i reference the AA1 deine in FileA.cpp in the if statement in FileB.h?
is this line correct? #if AA != FileA.AA1
how would i call a define in another file in #if preprocessor???

You can't. #define macros are not member variables in the sense that you are thinking about them at all. If you want FileA and FileB to have similar #defines, you have to use naming conventions to differentiate them.
Typically you would prefix your #defines with an identifier, such as #define FILEA_AA 125 and #define FILEB_AA 300.
Then you can compare them with preprocessor directives as follows:
#if FILEA_AA == FILEB_AA
/* Code goes here */
#endif

You cannot do this with #define. #defineed identifier is not a variable. #define is a simple text replacement performed by the preprocessor before the compiler really gets started.
Simplistically what happens is something like this: Some file includes FileB.h. This effectively pastes FileB.h into the including file, replacing the include statement. Shortly thereafter the preprocessor finds the include of FileA.h and does the same thing: pastes in FileA.h. You wind up with something like:
#define AA 1
#define BB 2
#define CC 3
#define AA 1
#define BB 2
#define CC 3
#if AA != FileA.AA //is this the way to call AA1 variable in FileA??
#error "Mismatch variable"
#endif
This repeats the definitions. A decent compiler will spit out a warning if they do not match. For example, if I force a mismatch:
..\src\main.cpp:9:0: warning: "AA" redefined [enabled by default]
#define AA 2
^
..\src\main.cpp:3:0: note: this is the location of the previous definition
#define AA 1
I usually run with warnings treated as errors, so I wouldn't bother going any further. (Side note on why I take this draconian approach: A compiler error means the syntax is bad and the code is not executable. A warning means while the code can be executed it very likely won't do what you intend it to do. If the program's not going to work, why bother building it?)
So how do we get around this?
We take a lesson from the great and mighty Sauron and craft One Header to Rule them all. After all, If the values must be in lock-step, why repeat them? That way lies only madness and bugs. The only downside with this approach is filthy hobbitsies stealing the precious. Doesn't happen all that often.
Common definitions are moved to a header used by other headers. In this model, FileA.h and FileB.h both #include "coredefs.h"which contains all of the core definitions like AA and its ilk. Since this coredefs.h is included by pretty much everyone, read up on Include Guards.
coredefsh. is:
#ifndef COREDEFS_H
#define COREDEFS_H
#define AA1 1
#define BB2 2
#define CC3 3
#endif
FileA.h is:
#ifndef FILEA_H
#define FILEA_H
#include "coredefs.h"
// other File A stuff here
#endif
FileB.h is:
#ifndef FILEB_H
#define FILEB_H
#include "coredefs.h"
// other File B stuff here
#endif

Related

Is there an elegant solution for checking whether a preprocessor symbol is defined or not

Since preprocessor don't report an error when checking value of preprocessor's symbol that isn't actually defined (usually due to the lack of #include "some_header.h"), I use this cumbersome three line construction with "defined":
#if !defined(SOME_SYMBOL)
#error "some symbol isn't defined"
#endif
#if SOME_SYMBOL == 1
// Here is my conditionally compiled code
#endif
And the way with "#ifndef" is the same.
Is there a more elegant way to perform this check?
In your construction you could use an else block to skip the check for defined:
#if SOME_SYMBOL == 1
// Here is my conditionally compiled code
#else
// error
#endif
But in principle the comments are right. #if !defined and the shorthand #ifndef are the two available versions.
Currently, you are checking if SOME_SYMBOL is equals to 1. Do you execute different code based on that value ?
If not, you could simply use:
#ifdef SOME_SYMBOL
// Here is my conditionally compiled code
#else
// error
#endif
And now it's a short step to the typical c++ include guards. Copying from that wikipedia link, here is a grandparent.h file:
#ifndef GRANDPARENT_H
#define GRANDPARENT_H
struct foo {
int member;
};
#endif /* GRANDPARENT_H */
Now, even if you end up including this header twice, it will only be executed once.

C++ `ifdef` with concatenation of macros values

Can I achieve something similar to following code:
#define MODULE base
#if defined (MODULE ## _dll) <-- this should do `#ifdef base_dll`
...
#else
...
#endif
second line is obviously wrong. Can I do this somehow?
Thanks
I don't think it is possible to check the definition of token-pasted macro like that (at least I don't know the way) but you can do this:
#define JOIN_INTERNAL(a,b) a ## b
#define JOIN(a,b) JOIN_INTERNAL(a,b)
// switch 1/0
#define base_dll 1
#define MODULE base
#if JOIN(MODULE,_dll)
// the base_dll is 1
#else
// the base_dll is 0 or not defined (in MSVC at least)
#endif
Perhaps if you describe what do you actually want to achieve there might be another way to do that.

Generating an error if checked boolean macro is not defined

I have several configuration files each one containing the definition of some boolean macro, to be set to 0 or 1. Then, in my code, I check the value of such a macro to decide which part of the code to activate. Now comes the tricky part: I want to be sure that the header containing the definition of my macro has been included.
In the following example, if I forget to include the header file containing FOO definition, the compiler will print "world!", while I would like instead that it generated an error.
//in the configuration header file
#define FOO 1
//in a cpp file
#if FOO //I would like this to generate an error if I forgot to include the header file
#pragma message "Hello"
#else
#pragma message "world!"
#endif
Is it possible to achieve such a behaviour? How?
To clarify, I am not asking how to generate an error if a macro is not defined, but if it is possible to transform the #if FOO line so that, at the same time, it checks the boolean value and generates an error if FOO is not defined.
The point of having this would be that developers would know that their code should contain
SPECIAL_MACRO(FOO)
which, at the same time, check the boolean value of FOO as if it was an #if FOO statement, and prevents them from forgetting the inclusion of the header defining FOO.
Colleagues (hi Hartmut, Kurt) who maintained a large code base which was extensively configured with #defines ran exactly into the same problem. A simple mis-spelling, possibly in a make file, could result in subtle errors which were hard to track down. Their solution: Use function macros! In
#if SOME_COND()
// ...
#endif
the compiler complains if SOME_COND() is not defined, as opposed to a simple SOME_COND which will be replaced by 0 if undefined. I like it because it can be used to transport several values without cluttering the code up with additional #ifdefs.
The accepted answer of using function-macros is good, but if you want to keep normal macros - and still use the value of FOO if defined and generate an error otherwise you could do:
#if FOO / defined(FOO)
#else
#endif
If FOO is not defined it will trigger integer division by zero.
What about using the -Wundef gcc preprocessor option? This will only generate a warning, which can easily be turned to an error with -Werror=undef.
Macro CHECK(x) will:
fail if macro x is undefined,
evaluate to 00 if x is defined to 0
evaluate to 01 if x is defined to 1
$ cat main.cpp
#define CAT(x, y) x##y
#define CHECK(x) CAT(0, x)
// usage
#define COND0 0
#define COND1 1
#if CHECK(COND)
#endif
#if CHECK(COND0)
#pragma message "defined 1"
#else
#pragma message "defined 0"
#endif
#if CHECK(COND1)
#pragma message "defined 1"
#else
#pragma message "defined 0"
#endif
$ g++ main.cpp
main.cpp:9:1: error: user-defined literal in preprocessor expression
9 | #if CHECK(COND)
| ^~~~~
main.cpp:15:17: note: ‘#pragma message: defined 0’
15 | #pragma message "defined 0"
| ^~~~~~~~~~~
main.cpp:19:17: note: ‘#pragma message: defined 1’
19 | #pragma message "defined 1"
| ^~~~~~~~~~~
I think can solve your problem in simple tricky solution. I change your code as below and my code understand that header.h doesn't exist and show error to me.
#if FOO == 1
#pragma message "Hello"
#elif FOO == 2
#pragma message "world!"
#else
throw std::invalid_argument("Header didn't add to project");
#endif
only you need to change your initial value for Foo.
because compiler activate Foo==0 when it doesn't find FOO, you shouldn't use 0 value for your configuration. you should leave zero for header absence situation.instead you must use values greater than zero(1 , 2, 3 , ...).
Foo==0 absence situation.
Foo==1 Configuration 1.
Foo==2 Configuration 2.
.
.
.

Is it possible to show the value of a #define at compile-time with ARM RVCT?

Question has been answered with VC and GCC in
How do I show the value of a #define at compile-time?
but is it possible to do it with ARM RVCT?
Actually I can do my own macro2string convertion as RVCT doesn't have stringification support. But I didn't even find "#pragma message" support in RVCT. It seems it has only something like
#pragma diag_error 223
which you must specify a tag, you can not freely output a string.
In fact I work on some legacy code now, here is an simplified example from the code base:
in product_conf.h:
#define VALUE_A 1
in platform_conf.h:
#ifndef VALUE_A
#define VALUE_A 2
#endif
in component_conf.h:
#ifndef VALUE_A
#define VALUE_A 3
#endif
in component.c:
#include product_conf.h
#include platform_conf.h
#include component_conf.h
It is a bit difficult to know VALUE_A is 1 or 2 or 3 when you are reading the component.c, actually in the real cases there can be 4~5 layers configurations and the c files may include or not include some certain conf.h, you have to go through the different header files case by case.
So I thought something like:
/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "=" VALUE(var[[)]]
#pragma message(VAR_NAME_VALUE(VALUE_A))
will help for a quick check, I just make the component and I will find out what is defined in the compiling output. This is doable with GCC, but I want to know how to do similar things with ARM RVCT.
or the only way to do it is:
#if (VALUE_A==1)
#warning "VALUE_A is 1"
#elif (VALUE_A==2)
#warning "VALUE_A is 2"
#elif (VALUE_A==3)
#warning "VALUE_A is 3"
#else
#error "VALUE_A is not properly defined!"
#endif

What's the meaning of #define when there is only 2 part?

I know the following 3 parts #define:
#define PI 3.4
which mean it will replace PI with 3.4.
But that's the meaning of 2 parts #define like this:
#define something
Will it replace something with null/empty string?
The following is the code example, I searched the file, only list the related lines
D:\mariadb\storage\pbxt\src\cache_xt.cc (23 hits)
Line 172: #ifdef xtPublic
Line 173: #undef xtPublic
Line 188: #define xtPublic
Line 325: xtPublic XTIndHandlePtr xt_ind_get_handle(..)
Line 378: xtPublic void xt_ind_release_handle(XTIndHandlePtr..)
Line 516: xtPublic xtBool xt_ind_copy_on_write(XTIndReferencePtr iref)
Line 597: xtPublic void xt_ind_lock_handle(XTIndHandlePtr handle)
Yes it meaning replace something with an empty string. But the important thing is now something is recognized by the preprocessor that it is "defined", so
#ifdef something
will pass after that #define (Line 172).
Also, it is common to use it for configurational or vendor-specific attributes (Line 325, ...), like
#if MSVC
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif
EXPORT void f();
// expand to '__declspec(dllexport) void f()' in MSVC
// expand to 'void f()' in other compilers
Those declarations are usually given within header files, as a means of preventing double inclusion of the same file. These are also called include guards.
#define something will result into something just defined. It will not cause a compiler error. It is used usually like
void getValue(IN int& x, OUT int& y). If you do #define IN and #define OUT it will not give a compiler error and anybody will get to know x is input and y is output
One more use is like
#ifndef __ABC_H__
#define __ABC_H__
...
#endif
This is to prevent reinclusion of for eg. "abc.h"
Its is nothing but Pre-Processor Directive, the #define just will direct the Header files to the considered Library files or can declares the constants.
Yes, it replaces the preprocessor with empty string. It helps is self-documenting the code without writing lengthy comments.