#ifdef with multiple tokens, is this legal? - c++

Today I came across some C++ code that contains an #ifdef clause like this:
#ifdef DISABLE_UNTIL OTHER_CODE_IS_READY
foo();
#endif
Note the space between "DISABLE_UNTIL" and "OTHER_CODE_IS_READY". Essentially there are two tokens specified in the #ifdef line.
My question is, is this legal C++ code? (g++ compiles it without any errors, and it apparently just ignores the second token). And if it is legal, should the second token have any effect?

The syntax you posted is not legal, and the intended meaning is unclear.
Depending on what you hope to accomplish, can you use || or && to combine them?
(of course if this is someone else's code, I'd just reject it as inappropriate / unusable)
#if defined(DISABLE_UNTIL) || defined(OTHER_CODE_IS_READY)
foo();
#endif

[C++11 16.1], [C++11 16.5] and, incidentally, [C99 6.10.1/4] all say that this is invalid.
if-group:
# if constant-expression new-line groupopt
# ifdef identifier new-line groupopt
# ifndef identifier new-line groupopt
Only one identifier is legal.
GCC's own documentation agrees.
My own tests suggest that only the first identifer is accepted, and the second is simply discarded; this may be to ease the implementation, but the standard does require a diagnostic here, so you should see this when you use the -pedantic flag at least†.
#include <iostream>
using namespace std;
#define A
#define B
int main() {
#ifdef A
std::cout << "a ";
#endif
#ifdef B
std::cout << "b ";
#endif
#ifdef C
std::cout << "c ";
#endif
#ifdef B C
std::cout << "bc ";
#endif
#ifdef C B
std::cout << "cb ";
#endif
return 0;
}
// Output: "a b bc"
// Note: "cb" *not* output
† Coliru's installation of GCC emits it with or without -pedantic.

Related

How to use preprocessor IF on DEFINE that is an ENUM member?

I am struggling with this for a while now, and cant get it to work!
I have a preprocessor define for LOG_LEVEL which defines what logs my program should emit.
I Have a lot of LOG points, so performance is needed,
therefore, no use of runtime check for log_level.
I trimmed my code to the minimal problematic construct which can be played with (here)[https://onlinegdb.com/u39ueqNAI]:
#include <iostream>
typedef enum {
LOG_SILENT=0,
LOG_ERROR,
LOG_WARNING,
LOG_INFO,
LOG_DEBUG
} E_LOG_LEVELS;
// this define is set using -DLOG_LEVEL=LOG_WARNING to the compiler.
#define LOG_LEVEL LOG_WARNING
int main() {
std::cout << "Logging Level Value is " << LOG_LEVEL << std::endl; // output 2 (correctly)
#if LOG_LEVEL==LOG_WARNING
std::cout << "Log Level Warning!" << std::endl; // outputs (correctly)
#endif
#if LOG_LEVEL==LOG_ERROR
std::cout << "Log Level Error!" << std::endl; // outputs (Why ??? )
#endif
return 0;
}
The main issue is that the #if LOG_LEVEL==LOG_* always true.
I also tried #if LOG_LEVEL==2 but this returned FALSE (uff).
what's going on ?
how can I test that a define is an enum value ?
You don't need the preprocessor for this. A normal
if (LOG_LEVEL <= LOG_WARNING)
will not create a runtime test when the condition involves only constants and the build has any optimization at all.
Modern C++ allows you to force the compiler to implement the conditional at compile-time, using if constexpr (...). This will prune away dead branches even with optimization disabled.
Finally, if you insist on using the preprocessor, and you can guarantee that the macro will use the symbolic name (you'll never build with g++ -DLOG_LEVEL=2), then you can
#define STRINGIFY(x) #x
#define STRINGY2(x) STRINGIFY(x)
#define PP_LOG_LEVEL STRINGY2(LOG_LEVEL)
#define LOG_LEVEL_IS(x) STRINGY2(LOG_LEVEL)==STRINGIFY(x)
then either
#if PP_LOG_LEVEL=="LOG_WARNING"
or
#if PP_LOG_LEVEL_IS(LOG_WARNING)
But I would recommend avoiding preprocessor string comparison for this.
If you do use the preprocessor, I recommend checking the actual value against a whitelist and using #error to stop the build in case LOG_LEVEL isn't set to any of the approved names.

"#define" vs "#define 1"

The 1 seems unnecessary (and possibly misleading) in the following example, but I have seen this multiple times when used for checking #ifdefs:
#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1
Is there a difference or reason for using the above versus a plain #define __NEWLIB_H__?
1 is true, so you can use the macro in an #if test. That's not usually very useful for header guards, but it certainly doesn't hurt. For other macros which might be tested in boolean expressions, the true value is definitely useful.
Some people just like the consistency. And that's the definition that gcc chooses by default if you put -D TESTME on the command line.
However,
#define __NEWLIB_H__ 1
is not cool unless it's in an implementation of the standard library, because names starting with two underscores (or an underscore and a capital letter) are reserved for use by the implementation, and should never be used in portable applications.
When used purely as an #include guard, there is no difference between
#ifndef __NEWLIB_H__
#define __NEWLIB_H__
and
#ifndef __NEWLIB_H__
#define __NEWLIB_H__ 1
However, in general, there is a distinction.
Compiler error
#ifndef ABCD
#define ABCD
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
Outputs the string "ABCD is 1"
#ifndef ABCD
#define ABCD 1
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
Outputs the string "ABCD is not 1"
#ifndef ABCD
#define ABCD 10
#endif
int main()
{
#if defined(ABCD) && (ABCD == 1)
std::cout << "ABCD is 1\n";
#else
std::cout << "ABCD is not 1\n";
#endif
}
#define by itself will replace the symbol with nothing.
On the other hand, #define 1, as you call it, will replace the symbol with 1 everywhere it is found in the file. So, for example, the following code:
#include <iostream>
#define EXAMPLE "hello"
int main()
{
std::cout << EXAMPLE;
return 0;
}
prints
hello
This is because EXAMPLE here is replaced with "hello", making the print statement equivalent to:
std::cout << "hello";
If we change the #define statement to this instead:
#define EXAMPLE
This will give a compile error:
main.cpp: In function ‘int main()’:
main.cpp:15:25: error: expected primary-expression before ‘;’ token
std::cout << EXAMPLE;
As to why you would ever use this second form of #define, it's because there is another processor directive that you can use called #ifdef:
#include <iostream>
#define EXAMPLE
int main()
{
#ifdef EXAMPLE
std::cout << "EXAMPLE defined.";
#endif
return 0;
}
This will print:
EXAMPLE defined.
Because #ifdef (and its relative #ifndef) only require that the symbol be defined, we don't really need to give it a value. It just needs to be there to work.
A common place you see this kind of stuff is with header guards (which is probably what you're seeing). You can also see it with platform identification, or even to determine whether the compiler is using C++ or not.

Exclude line from compilation via Makro C++

I've got some problem, which might be simple to solve.
I have code like this:
#define _MG_ALL //This might be defined in some other headerfile
#ifndef _MG_ALL
#define MG_ALL <?????>
#else
#define MG_ALL <nothing>
#endif
In the code it is used like this:
ALL foo = thisIsSomeFunc(foo);
This line should only be compiled, if _ALL is defined. This could also be solved by using this:
#ifdef ALL
foo = thisIsSomeFunc(int foo);
#endif
But I would prefer just one short macro in the same line.
What you could do is defining the macro like so:
#ifdef _ALL
#define ALL if(1)
#else
#define ALL if(0)
#endif
When you use it this it will produce code similar to this
ALL std::cout << "Debug Message" << std::endl;
==> if(1) std::cout << "Debug Message" << std::endl;
A good compiler should recognize the constant value in the if-statement and should only compile the right part (1 ==> if part, 0 ==> nothing).

using macros to place #ifdef in the code

I am trying to do something like this
#define VB_S #ifdef VERBOSE
#define VB_E #endif
so that in the code instead of writing
#ifdef VERBOSE
cout << "XYZ" << endl;
#endif
I can write
VB_S
cout << "XYZ" << endl;
VB_E
This gives me a compile time error: Stray '#' in the program.
Can anyone put light on what is the right way to do this
You can't put directives inside macros. (# inside a macro as another signification -- it is the stringizing operator and must be followed by a parameter id -- but the restriction is older than that meaning)
You could do something like this:
#ifdef VERBOSE
#define VB(x) x
#else
#define VB(x) do { } while (false)
#endif
VB(cout << "foo");
Similar to Erik's response:
#ifdef VERBOSE
#define VB(...) __VA_ARGS__
#else
#define VB(...) /* nothing */
#endif
Using a variadic macro has the benefit of allowing commas inside the VB() call. Also, AFAIK, you can remove the do...while.
I prefer the following:
#define VERBOSE 1
// or 0, obviously
if (VERBOSE)
{
// Debug implementation
}
This is a little more readable since VB_S doesn't mean anything to the average user, but if (VERBOSE) does.

How do I temporarily disable a macro expansion in C/C++?

For some reason I need to temporarily disable some macros in a header file and the #undef MACRONAME will make the code compile but it will undef the existing macro.
Is there a way of just disabling it?
I should mention that you do not really know the values of the macros and that I'm looking for a cross compiler solution (should work at least in GCC and MSVC).
In MSVC you could use push_macro pragma, GCC supports it for compatibility with Microsoft Windows compilers.
#pragma push_macro("MACRONAME")
#undef MACRONAME
// some actions
#pragma pop_macro("MACRONAME")
Using just the facilities defined by Standard C (C89, C99 or C11), the only 'disable' mechanism is #undef.
The problem is there is no 're-enable' mechanism.
As others have pointed out, if the header file containing the macro definitions is structured so that it does not contain any typedef or enum declarations (these cannot be repeated; function and variable declarations can be repeated), then you could #undef the macro, do what you need without the macro in effect, and then re-include the header, possibly after undefining its protection against reinclusion.
If the macros are not defined in a header, of course, you are stuck until you refactor the code so that they are in a header.
One other trick is available - if the macros are function-like macros and not object-like macros.
#define nonsense(a, b) b /\= a
int (nonsense)(int a, int b)
{
return (a > b) ? a : b;
}
The function nonsense() is defined fine, despite the macro immediately before it. This is because a macro invocation - for a function-like macro - must be immediately followed by an open parenthesis (give or take white space, possibly including comments). In the function definition line, the token after 'nonsense' is a close parenthesis, so it is not an invocation of the nonsense macro.
Had the macro been an argument-less object-like macro, the trick would not work:
#define nonsense min
int (nonsense)(int a, int b)
{
// Think about it - what is the function really called?
return (a > b) ? a : b;
}
This code defines a bogus function that's called min and is nonsensical. And there's no protection from the macro.
This is one of the reasons why the standard is careful to define which namespaces are reserved for 'The Implementation'. The Implementation is allowed to define macros for any purpose it desires or needs, of any type (function-like or object-like) it desires or needs, provided those names are reserved to the implementation. If you as a consumer of the services of The Implementation try to use or define a name reserved to the implementation, you must be aware that your code will probably break sooner or later, and that it will be your fault, not the fault of The Implementation.
Macros make my knees go weak, but wouldn't the most universal solution be to restructure your code so that you wouldn't need to reenable the macro again in the same source file? Wouldn't it be possible to extract some code into a separate function and a separate source file where you can undef the offending macro.
The macros come from some header file, so you should have access to their values. You can then do something like
#include <foo.h> // declares macro FOO
// Do things with FOO
#undef FOO
// do things without FOO
#include <foo.h> // reenable FOO
Your header should then be designed along these lines
#ifndef FOO
#define FOO do_something(x,y)
#endif
EDIT:
You may think that it's that easy:
#ifdef macro
#define DISABLED_macro macro
#undef macro
#endif
// do what you want with macro
#ifdef DISABLED_macro
#define macro DISABLED_macro
#endif
But it's not (like the following example demonstrates)!
#include <iostream>
#include <limits>
#include <windows.h>
#ifdef max
#define DISABLED_max max
#undef max
#endif
int main()
{
std::cout << std::numeric_limits<unsigned long>::max() << std::endl;
#ifdef DISABLED_max
#define max DISABLED_max
#endif
std::cout << max(15,3) << std::endl; // error C3861: "max": identifier not found
return 0;
}
Using #undef on the macro and re-including the original header is also not likely to work, because of the header guards.
So what's left is using the push_macro/pop_macro #pragma directives.
#pragma push_macro("MACRO")
#undef MACRO
// do what you want
#pragma pop_macro("MACRO")
There are specific rules for function-like macroses invokation in C/C++ language.
The function-like macroses have to be invoked in the following way:
Macros-name
Left parethesis
One token for each argument separated by commas
Each token in this list can be separared from another by whitespaces (i.e. actual whitespaces and commas)
With one trick you "disable preprocessor mechanism" with breaking rules for function-like macro invokation, but be still within a rules of function calling mechanism...
#include <iostream>
using namespace std;
inline const char* WHAT(){return "Hello from function";}
#define WHAT() "Hello from macro"
int main()
{
cout << (*WHAT)() << "\n"; // use function
cout << (WHAT)() << "\n"; // use function
cout << WHAT () << "\n"; // use macro
return 0;
}