Can #if pre-processor directives be nested in C++?
Yes, we can. The #endif
statement matches to the previous #if
#ifdef
or #ifndef
etc for which there hasn't been a corresponding #endif
.
e.g.
#if ----------|
#if -----| |
#endif ---| |
#endif --------|
Can C# preprocessor directives be nested?
Yes, they can be nested.
#define A
#define B
void Main()
{
#if A
#if B
Console.WriteLine("A and B");
#else
Console.WriteLine("A and not B");
#endif
#else
#if B
Console.WriteLine("B and not A");
#else
Console.WriteLine("neither A nor B");
#endif
#endif
}
Outputs:
A and B
Here's a .NET Fiddle for you to try.
You can comment out the two lines at the top individually to get different results, like:
#define A
// #define B
Outputs:
A and not B
Here's the same code with indentation that makes it clearer, though I would not indent the code like this. Overuse of conditional directives like this is a code smell in my opinion.
#define A
// #define B
void Main()
{
#if A
#if B
Console.WriteLine("A and B");
#else
Console.WriteLine("A and not B");
#endif
#else
#if B
Console.WriteLine("B and not A");
#else
Console.WriteLine("neither A nor B");
#endif
#endif
}
Can you nest C preprocessor directives?
Though your syntax is invalid, the answer to your question is technically yes. But it can only be accomplished by nasty tricks that make your code unreadable and unmaintainable.
See also: http://www.ioccc.org/years.html#1995_vanschnitz and http://www.ioccc.org/years.html#2004_vik2
Can the pre-processor directives like #include be placed only at the top of the program code?
An #include
directive can be placed anywhere in a source file, but in C an identifier can usually not be used before it has been declared. That's the reason why you put the #include
directive at the begining of your source file.
void foo(void)
{
printf("Hello world\n");
}
extern int printf(const char *, ...); // Error, the declaration should be put
// before the actual call
Pre-processor Directives (#if and #endif) not working in C
This preprocessor check
#if a
...
#endif
is performed at compile time and is completely unrelated to
int a;
For #if a
to be true
you need a previous statement such as
#define a 42
For #if a
to be false
you need a previous statement such as
#define a 0
However if you simply have
#define a
which in itself is valid, but does not define a testable value, then the compiler will issue an error like
error C1017: invalid integer constant expression
But having #define a 42
means you cannot then use a
to define a variable because
int a;
will expand to
int 42;
which is an error.
C++ nested preprocessor directions
You can't have a #if
inside a #define
, but you can have a #define
inside the code controlled by a #if
.
For example:
#ifdef DEBUG
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
debug-code \
last-part
#else
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
last-part
#endif
If first-part and last-part are big enough, you might want to define macros for them.
I'm not saying this is a good idea, but it does do what you were trying to do.
EDIT: Thanks to @okorz001 for suggesting a cleaner alternative in a comment:
#ifdef DEBUG
#define DEBUG_CODE (blah, blah)
#else
#define DEBUG_CODE /* nothing */
#endif
#define BINARY_VECTOR_RETURN_OPERATOR(optype) \
first-part \
DEBUG_CODE;
last-part
Obviously the real code would use better names.
How do you indent preprocessor statements?
Just because preprocessing directives are "normally" not indented is not a good reason not to indent them:
#ifdef __WIN32__
#include <pansen_win32>
#else
#include <..>
#ifdef SOMEOTHER
stmts
#endif
maybe stmts
#endif
If you frequently have multiple levels of nesting of preprocessing directives, you should rework them to make them simpler.
Related Topics
Search 25 000 Words Within a Text
Template Tricks with Const Char* as a Non-Type Parameter
What Is Allowed in a Constexpr Function
Automatically Generate C++ File from Header
Virtual Destructor: Is It Required When Not Dynamically Allocated Memory
How to Iterate Backwards Through an Stl List
How to Convert a String of Hex Values to a String
Preventing Non-Const Lvalues from Resolving to Rvalue Reference Instead of Const Lvalue Reference
Differentiate Between a Unix Directory and File in C and C++
What's the Difference Between New Char[10] and New Char(10)
What's the Best Technique for Exiting from a Constructor on an Error Condition in C++
How to Change an Executable's Properties? (Windows)
C++ Template Instantiation: Avoiding Long Switches
Template Class Member Function Only Specialization