Multiple #define within #ifdef or #ifndef - c++

This is a simple question, but I have not ran across similar code before to know the answer. Basically, am I allowed to have more than two #define in an #ifdef or #ifndef statement? For a basic example:
#ifdef __GNUC__
#define HELLO(x) x
#define WORLD(y) y
#else
#define __attribute__(x)
#define expect(expression, value) (expression)
#endif
Thank you

Of course you are. This is perfectly valid.
You can have as many C statements or preprocessor directives within a preprocessor block as you want.

Yes, you may have as many preprocessor directives or just normal C++ statements between an #ifdef / #ifndef ... [#else] ... #endif block as you want.
This is a simple enough question that you probably should have tried it before asking though.

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.

Why is assert defined as (void)0?

Why
#define assert(expression) ((void)0),
rather than
#define assert(expression)
is used in release mode?(strictly speaking, when NDEBUG is defined)
I heard that there are some reasons, but I've forgot it.
((void)0) defines assert(expression) to do nothing.
The main reason to use it is that #define assert(expression) would allow assert(expression) to compile without a semicolon but it will not compile if the macro is defined as ((void)0)
The reason why ((void)0) is used in empty macros is make them behave like a function, in the sense that you need to specify the semicolon ; at the end
For example:
#define assert1(expression) (void)0
assert(1) // compile error, missing ;
#define assert2(expression)
assert(1) // works

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/C++ #define Macro inside macro?

I would like something like:
#define C_OR_CPP(C__, CPP__) #ifdef __cplusplus\
CPP__\
#else\
C__\
#endif
Is it possible?
Maybe some dirty hack with #include ?
Reason:
I make a header where a struct uses a member variable of type vector<stuff>*, but in C i want it to simply be void*, you know.
TIA
What's the problem with
#ifdef __cplusplus
#define C_OR_CPP(C, CPP) CPP
#else
#define C_OR_CPP(C, CPP) C
#endif
(Leaving names with double underscore to the implementation per phresnel remark)
My English is poor, and I'm sorry for language mistakes and typos if any.
If #ifdef must not wrap the macro invocation, there is a solution not so graceful.
g++ only:
You may try this in selective occasions. But if there are commas in a or b, workarounds are still needed.
It's simply based on the fact that __cplusplus is defined to "1" when in a C++ environment and remains itself while not.
#define SELECT1(a, b) a
#define SELECT__cplusplus(a, b) b
#define xcat(a,b) a##b
#define concat(...) xcat(__VA_ARGS__)
#define C_OR_CPP(C, CPP) concat(SELECT, __cplusplus)(C, CPP)
C_OR_CPP(1, 2)
Other Environments
Check the __cplusplus macro, a compiler that comforming to standard C++ should generate
#define __cplusplus value
and value should >= 199711L
Not in C++. But you can
#ifdef __cplusplus
# define CPP
#else
# define C
#endif
I assume this is just a pathological example by you. Note also that double underscore is reserved to library implementors (see 17.6.4.3.2 Global names).
vector, but in C i want it to simply be void, you know.
So, what speaks against a solution like
struct Foo {
#ifdef __cplusplus
...
#else
...
#endif
};
or what speaks against providing different APIs for different programming languages?
AProgrammer already given you the right answer, but the answer to the "is it possible" part of the question is no. Macro expansion doesn't occur until after all preprocessor directives have been handled, so any macro that expands into a #define or #ifdef will be passed to the compiler as regular source text, which will cause the compiler to yak.

Using #define to include another file in C++/C

I want to define a macro which includes another header file like so:
#define MY_MACRO (text) #include "__FILE__##_inline.inl"
So that when the preprocessor parses file person.h, MY_MACRO(blahblah) expands to
#include "person.h.inline.inl"
any hints on how to do this ?
It's not possible to use #define to construct other preprocessor directives, unless you run the preprocessor twice.
But in your case even running the preprocessor twice won't help because the #include must be a single string of the form "..." or <...>.
You cannot use __FILE__ because that is already quoted, and #include doesn't support string concatenation. But you can use macros after #include:
#define STRINGIZE_AUX(a) #a
#define STRINGIZE(a) STRINGIZE_AUX(a)
#define CAT_AUX(a, b) a##b
#define CAT(a, b) CAT_AUX(a, b)
#define MY_MACRO(file, name) STRINGIZE(CAT(file, CAT(name, _inline.inl)))
#include MY_MACRO(aaaa, qqq)
You should use the equivalent Boost.Preprocessor macros instead of CAT and STRINGIZE to prevent global namespace pollution.
You can't write other pre-processor directives using the pre-processor. However, I believe you could define just the file name:
#define MY_MACRO(name) "__FILE__##name_inline.inl"
#include MY_MACRO(name)
The pre-processor runs multiple times until there are no further substitutions it can make, so it should expand the name first and then #include the referenced file.
EDIT: I just tried it and the pre-processor can't handle the quotes like that.
#define MY_MACRO(x) <__FILE__##x_inline.inl>
#include MY_MACRO(foo)
works OK, but <> may not be what you wanted.
EDIT2: As pointed out by sth in comments, the __FILE__ does not expand correctly, which makes this probably not what you want after all. Sorry.
#if 0 /*Windows*/
#define MKDIR_ENABLER <direct.h>
#define MY_MKDIR(x,y) _mkdir((x))
#else /*Linux*/
#define MKDIR_ENABLER <sys/stat.h>
#define MY_MKDIR(x,y) mkdir((x),(y))
#endif
#include MKDIR_ENABLER
int main(void)
{
MY_MKDIR("more_bla",0644);
return 0;
}
This code includes the appropriate header file for mkdir (because it's different on UNIX and Windows) and introduces a nice wrapper for it.