Can I use #undef this way? - c++

I want to get some settings I store in the registry, and if they differ from a #define I want to redefine it, could I do it this way?:
#define DEFINED_X "testSetting"
void LoadConfig()
{
regConfigX = some value previusly stored in the registry;
if(regConfigX!=DEFINED_X)
{
#undef DEFINED_X
#define DEFINED_X regConfigX
}
}
I tought #define was used only when compiling, would this code work when running the compiled exe?

No. #define and #undef are preprocessing directives; they are evaluated before the source code is compiled.
You need to use a variable for this, not a macro.

#define and #undef occur before your source code even hits the compiler. Anything to do with #defines can't happen at runtime.
You should check out the Boost preprocessor library, too.

No, use a static variable to store the value of DEFINED_X.

Related

How does #define know when to stop looking?

I use a macro in C++ to switch between compiling logging or not:
#define MAYBE_LOG(msg)
#ifdef PRINT_MSGS
ALWAYS_LOG(msg)
#endif
How does the #define know where the ending is? The #endif refers to the #ifdef, not the #define.
#define ends at end of the line (which might be extended with final \)
The code in the question does two separate things: it defines a macro named MAYBE_LOG with no body and, if PRINT_MSGS is defined, it uses a macro named ALWAYS_LOG. If that's not what it's supposed to do, then, yes, it needs to be changed. Since the question doesn't say what the code is supposed to do, this is just a guess:
#ifdef PRINT_MSGS
#define MAYBE_LOG(msg) ALWAYS_LOG(msg)
#else
#define MAYBE_LOG(msg)
#endif
The reason for doing it this way (and not using \ on each line to extend the macro definition is that you can't put #if conditions inside the definition of a macro.

What does #define do if you only have an identifer

typically #define would be used to define a constant or a macro. However it is valid code to use #define in the following way.
#define MAX // does this do anything?
#define MAX 10 // I know how to treat this.
So, if I #define MAX 10, I know my pre-processor replaces all instances of MAX with 10. If someone uses #define MAX by itself however with no following replacement value, it's valid. Does this actually DO anything?
My reason for asking is that I am writing a compiler for c in c++ and handling preprocessor directives is required but I haven't been able to find out if there is any functionality I need to have when this occurs or if I just ignore this once my preprocess is done.
My first instinct is that this will create a symbol in my symbol table with no value named MAX, but it is equally possible it will do nothing.
As an add in question which is kind of bad form I know, but I'm really curious. Are there situations in real code where something like this would be used?
Thanks,
Binx
A typical example are header guards:
#ifndef MYHEADER
#define MYHEADER
...
#endif
You can test if something is defined with #ifdef / ifndef.
It creates a symbol with a blank definition, which can later be used in other preprocessor operations. There are a few things it can be used for:
1) Branching.
Consider the following:
#define ARBITRARY_SYMBOL
// ...
#ifdef ARBITRARY_SYMBOL
someCode();
#else /* ARBITRARY_SYMBOL */
someOtherCode();
#endif /* ARBITRARY_SYMBOL */
The existence of a symbol can be used to branch, selectively choosing the proper code for the situation. A good use of this is handling platform-specific equivalent code:
#if defined(_WIN32) || defined(_WIN64)
windowsCode();
#elif defined(__unix__)
unixCode();
#endif /* platform branching */
This can also be used to dummy code out, based on the situation. For example, if you want to have a function that only exists while debugging, you might have something like this:
#ifdef DEBUG
return_type function(parameter_list) {
function_body;
}
#endif /* DEBUG */
1A) Header guards.
Building on the above, header guards are a means of dummying out an entire header if it's already included in a project that spans multiple source files.
#ifndef HEADER_GUARD
#define HEADER_GUARD
// Header...
#endif /* HEADER_GUARD */
2) Dummying out a symbol.
You can also use defines with blank definitions to dummy out a symbol, when combined with branching. Consider the following:
#ifdef _WIN32
#define STDCALL __stdcall
#define CDECL __cdecl
// etc.
#elif defined(__unix__)
#define STDCALL
#define CDECL
#endif /* platform-specific */
// ...
void CDECL cdeclFunc(int, int, char, const std::string&, bool);
// Compiles as void __cdecl cdeclFunc(/* args */) on Windows.
// Compiles as void cdeclFunc(/* args */) on *nix.
Doing something like this allows you to write platform-independent code, but with the ability to specify the calling convention on Windows platforms. [Note that the header windef.h does this, defining CDECL, PASCAL, and WINAPI as blank symbols on platforms that don't support them.] This can also be used in other situations, whenever you need a preprocessor symbol to only expand to something else under certain conditions.
3) Documentation.
Blank macros can also be used to document code, since the preprocessor can strip them out. Microsoft is fond of this approach, using it in windef.h for the IN and OUT symbols often seen in Windows function prototypes.
There are likely other uses as well, but those are the only ones I can think of off the top of my head.
It doesn't "do" anything in the sense that it will not add anything to a line of code
#define MAX
int x = 1 + 2; MAX // here MAX does nothing
but what an empty define does is allow you to conditionally do certain things like
#ifdef DEBUG
// do thing
#endif
Similarly header guards use the existance of a macro to indicate if a file has already been included in a translation unit or not.
The C Preprocessor (CPP) creates a definitions table for all variables defined with the #define macro. As the CPP passes through the code, it does at least two things with this information.
First, it does a token replacement for the defined macro.
#define MAX(a,b) (a > b) ? (a) : (b)
MAX(1,2); // becomes (1 > 2) ? (1) : (2);
Second, it allows for those definitions to be searched for with other preprocessor macros such as #ifdef, #ifndef, #undef, or CPP extensions like #if defined(MACRO_NAME).
This allows for flexibility in using macro definitions in those cases when the value is not important, but the fact that a token is defined is important.
This allows for code like the following:
// DEBUG is never defined, so this code would
// get excluded when it reaches the compiler.
#ifdef DEBUG
// ... debug printing statements
#endif
#define does a character-for-character replacement. If you give no value, then the identifier is replaced by...nothing. Now this may seem strange. We often use this just to create an identifier whose existence can be checked with #ifdef or #ifndef. The most common use is in what are called "inclusion guards".
In your own preprocessor implementation, I see no reason to treat this as a special case. The behavior is the same as any other #define statement:
Add a symbol/value pair to the symbol table.
Whenever there is an occurrence of the symbol, replace it with its value.
Most likely, step 2 will never occur for a symbol with no value. However, if it does, the symbol is simply removed since its value is empty.

Why using if statements in preprocessor defines?

When exploring a source package, I discovered that some if statements were defined by preprocessor directives and then used in the code like the example below:
#ifdef _WIN32
#define OSisWindows() true
#define OSisLinux() false
#elif defined(__linux__)
#define OSisLinux() true
#define OSisWindows() false
#endif
if ( OSisWindows() )
{
// do something
}
if ( OSisLinux() )
{
// do something else
}
Is there a difference between using this and simple defines like _WIN32 or __linux__ ?
Well, you can't use a macro directly in your code like:
if ( _WIN32 ) {
...
}
on linux for example because it isn't defined so they are simply mapping the macro to a boolean expression.
In in end, it's really a style decision though... they could have certainly done:
#ifdef _WIN32
...
#endif
Assuming the macros are defined, the advantage of using an if..else statement over an #if .. #else directive is all code paths are compiled in the first case so if there are compile errors the compiler is able to see them in all the code paths. Of course this isn't always possible as some code paths may be platform dependent code.
In addition to what's already been written it's another layer of abstraction. If for example the syntax for _WIN32 changes or you want to explicitly compile for windows without relying on the flag, you'd have to change your complete code in case you would have used _WIN32 directly. In this case you could just change the preprocessor directives.
Is there a difference between using this and simple defines like _WIN32 or linux ?
No, this is simple macro abuse.

C++ - Two names in class declaration (macros)

I'm working on existing C++ code, which is using a kind of API.
While browsing the code I found a strange syntax that I saw now for the first time and I can't figure out what it does or how such is called.
It goes like this:
class KINDA_API foobar : public foo {
// Some class declarations
};
Everything after foobar is understandable for me. But what means that KINDA_API? What does this do? Is that any kind of advanced derivation or something like that?
Maybe there is any other Thread that answers this, and I also searched for it, but I don't even know how this is called ^^'
Usually when you see OMGWFT_API declarations in this exact way, this is a 'magic switch' for building a library in correct "mode":
static linking - OMGWFT_API replaced by "" (empty string)
dynamic linking - DLL - OMGWFT_API replaced by declspec(dllexport)
dynamic linking - EXE - OMGWFT_API replaced by declspec(dllimport)
i.e.
#ifdef BUILD_ME_AS_STATICLIB
#define OMGWFT_API
#else
#ifdef BUILD_ME_AS_DLL
#define OMGWFT_API declspec(dllexport)
#else
#define OMGWFT_API declspec(dllimport)
#endif
#endif
This is of course just an sketch of example, but I think you get the point now. Keywords are taken from MSVC not GCC< because I accidentially happen to remember them.
The "BUILD_ME_AS...." macros would be then defined via project options or -D command line switch.
However, it the OMGWFT_API can be set to have any meaning, so be sure to grep/search for a #define that sets this.
I guess it is a #define-d macro that does some "magic" before compile.
If you look through the existing call you are likely to find somthing like:
#ifdef _WIN32
#define KINDA_API <windows specific attribute>
#elif __linux
#define KINDA_API <linux specific attribute>
etc...
These macros are more likely conditioned on compilers and/or their versions rather than operating system but you get the idea...

Temporary macro to store another macro and then reverting back

I want to have more control over macros such as assertions (and some logging macros that are not directly under my control). So I decided to do something like this, expecting it to work (in case somebody is wondering, the reason it does not work is that the last undef of MY_ASSERT_COPY invalidates MY_ASSERT right before it).
#ifndef ENABLE_FULL_ERROR_ASSERTS
#define MY_ASSERT_COPY MY_ASSERT
#undef MY_ASSERT
#define MY_ASSERT
#endif
// Code for my current class, which happens to be header only
#ifndef ENABLE_FULL_ERROR_ASSERTS
#undef MY_ASSERT
#define MY_ASSERT MY_ASSERT_COPY
#undef MY_ASSERT_COPY
#endif
Now I know a few ways around it, one being to define another macro for assertions just for that file, which I can then turn off without affecting assertions in any other part of the program. I initially thought this was a really elegant solution (before I found out it did not compile) that will allow me to use MY_ASSERT everywhere and then simply turn it off for particular files.
Since the above doesn't work, is there a workaround that will allow me to selectively kill the macro without affecting the surrounding code and without defining another substitute macro like #define MY_ASSERT_FOR_VECTORS MY_ASSERT
Some compilers provide #pragma push_macroand #pragma pop_macro to save and restore macro state.
Limited portability though.
This may not work in all situations, but maybe you could simply undef the macros, define them as you wish and then undef them again.
The next time your code uses some of these macros it should #include the header files where they were initially defined so it will define those macros again.
One safe option would be:
#ifndef ENABLE_FULL_ERROR_ASSERTS
#undef MY_ASSERT
#define MY_ASSERT ....
#endif
// Code for my current class, which happens to be header only
#ifndef ENABLE_FULL_ERROR_ASSERTS
#undef MY_ASSERT
#include "headers.h" //etc
// line above should redefine the macros
#endif