I have some code that has an existing preprocessor conditional directives of the form:
#ifndef SYMBOL_XYZ
// some code here
#else
// some other code here
#endif
and I want to add a new condition that supersedes that logic, and I think this is the way to do it but I'm unsure of the subtleties around nesting and precedence when it comes to the C pre-processor.
#ifdef NEW_SYMBOL_ABC
// some new code here that takes precedence over the other two conditions
#else
#ifndef SYMBOL_XYZ
// some code here
#else
// some other code here
#endif
#endif
Do I have that right? Would it be equivalent to do:
#ifndef NEW_SYMBOL_ABC
#ifndef SYMBOL_XYZ
// some code here
#else
// some other code here
#endif
#else
// some new code here that takes precedence over the other two conditions
#endif
Try this .. .
#ifdef NEW_SYMBOL_ABC
// some new code here that takes precedence over the other two conditions
#elif !defined(SYMBOL_XYZ)
// some code here
#else
// some other code here
#endif
Above is what I commonly use and should work with gcc for sure.
Not sure, but should work with visual c++ and other compilers.
Related
I have a question about Pre-processor directives in c++:
For example:
#ifndef QUESTION
//some code here
#ifndef QUESTION
//some code here
#endif
#endif
Can we use it in this way, and can the C++ compiler match the ifndef and endif in the right way?
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 --------|
Yes, you can nest #if/#endif blocks. Some C coding styles would tell you to write
#ifdef CONDITION1
# ifdef CONDITION2
# endif
#endif
using spaces to denote the level of nesting.
In your code, the #ifndef QUESTION section will be discarded unless you #undef QUESTION.
Good luck!
Is it possible to put a #endif inside a #if as the block's 'content' not as the pair #endif for the #if?
#if (SOME_CONDITION)
#if (ANOTHER_CONDITION)
#endif // pair endif for #if (SOME_CONDITION)
#if (SOME_CONDITION)
#endif // pair endif for #if (ANOTHER_CONDITION)
#endif // pair endif for #if (SOME_CONDITION)
If this is not possible how to conditionally compile a #if ... #endif pair?
This is what I was doing.
I was modifying a code base that we bought from another company. To compile it with and without my modifications easily I was using a macro say like shown below.
#if (MY_COMPANY_EDITS_ENABLED)
// My Modified code goes here
#else
// unmodified code from another company
#endif
In this way I could easily compile in/out my modifications while maintaining readability about my edits. I was using the same #if #else #endif blocks everywhere. But then I came across a code that is being compiled in, in the original unmodified code base, based on some macro value.
#if (FEATURE_A_IS_ENABLED)
// Line 1
// Line 2
#endif
But I want to compile this code [Line 1 and Line 2] regardless of the macro value FEATURE_A_IS_ENABLED
My first thought was to follow the same convention that I used till now [to maintain readability about my edits].
#if (MY_COMPANY_EDITS_ENABLED)
//#if (FEATURE_A_IS_ENABLED)
#else
#if (FEATURE_A_IS_ENABLED)
#endif
// Line 1
// Line 2
#if (MY_COMPANY_EDITS_ENABLED)
// #endif
#else
#endif
#endif
Then I realized this is not possible.
I know, alternative methods exist to achieve the same. But was wondering whether I could use the same convention
#if (MY_COMPANY_EDITS_ENABLED)
// My Modified code goes here
#else
// unmodified code from another company
#endif
in this case too.
No, it's not possible. The first #endif will be matched with the most recent #if or #else, so your code will be interpreted like this:
#if (SOME_CONDITION)
#if (ANOTHER_CONDITION)
#endif // pair endif for #if (ANOTHER_CONDITION)
#if (SOME_CONDITION)
#endif // pair endif for the second #if (SOME_CONDITION)
#endif // pair endif for the first #if (SOME_CONDITION)
This is not possible, as the preprocessor only does a single pass over your file, and the #endif gets matched with the preceding #if. If you want to make an #if/#endif block conditional, then just nest it inside another #if/#endif block:
#if CONDITION_A
# if CONDITION_B
...
# endif /* CONDITION_B */
#endif /* CONDITION_A */
Put another way, it's not possible to have preprocessing directives construct other preprocessing directives, as the output from the initial "construction" phase will not be reparsed by the preprocessor.
The (silly) example below wouldn't work either for example, even assuming the newlines wouldn't be an issue (which they would be here):
#if DEFINE_X_TO_FIVE
#define X
#endif
#if DEFINE_X_TO_FIVE
5
#endif
I recommend making the changes based on feature sets rather than whether or not they are yours or not then group them together to make a given version (MY_COMPANY_EDITS_ENABLED) or whatever:
#if (MY_COMPANY_EDITS_ENABLED)
#define FEATUREA
#define FEATUREB
#define FEATUREC
#define FEATURED
#else
#define FEATUREA
#undef FEATUREB
#undef FEATUREC
#undef FEATURED
#endif
#ifdef FEATUREA
//do some feature A stuff
#endif
// do code
#ifdef FEATUREB
//do some feature B stuff
#endif
#ifndef FEATUREC
//do some stuff if not feature C
#endif
// etc...
This is a lot more flexible in the long run and lets you switch changes features on and off with a rebuild.
Off course you can nest your preprocessor directives:
#ifdef CONDITION1
// some code here
# ifdef CONDITION2
// some else here
# endif
#endif
But make sure to end each condition properly.
See also: http://www.ioccc.org/years.html#1995_vanschnitz and http://www.ioccc.org/years.html#2004_vik2
Let us presume that we have the next fragment of code in a C program:
#ifdef USE_FORK
CODE...
#else
phtread_t thread;
pthread_create(&thread,NULL,clientDispatch,&client);
#endif
Can you explain me what are these directives, ifdef, else, endif. What happens when we use C directives?
Quoting cplusplus.com,
Preprocessor directives are lines included in the code of programs preceded by a hash sign (#). These lines are not program statements but directives for the preprocessor. The preprocessor examines the code before actual compilation of code begins and resolves all these directives before any code is actually generated by regular statements.
#ifdef allows a section of a program to be compiled only if the macro that is specified as the parameter has been defined, no matter which its value is. For example:
#ifdef TABLE_SIZE
int table[TABLE_SIZE];
#endif
In this case, the line of code int table[TABLE_SIZE]; is only compiled if TABLE_SIZE was previously defined with #define, independently of its value. If it was not defined, that line will not be included in the program compilation.
The #if, #else and #elif (i.e., "else if") directives serve to specify some condition to be met in order for the portion of code they surround to be compiled. The condition that follows #if or #elif can only evaluate constant expressions, including macro expressions. For example:
#if TABLE_SIZE > 200
#undef TABLE_SIZE
#define TABLE_SIZE 200
#elif TABLE_SIZE < 50
#undef TABLE_SIZE
#define TABLE_SIZE 50
#else
#undef TABLE_SIZE
#define TABLE_SIZE 100
#endif
int table[TABLE_SIZE];
Notice how the entire structure of #if, #elif and #else chained directives ends with #endif.
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1.7.html
This link should explain to you the directives. Additionally, with the directives if the condition after #ifdef becomes true then the compiler will compile the following code otherwise it would look for the next directive and compile the following code.
In your example therefore, if USE_FORK is a true expression then the CODE... will be compiled, otherwise, the lines with definition to threads will be compiled.
Its a conditional group, a preprocessor command. If the macro is defined i.e. USE_FORK then the code will executed up to #else, if the macro is not defined then the code at #else will execute up to #endif
I want to print info only if _DEBUG is defined
#define DEBUG(y) y == true ? #define _DEBUG true : #define _DEBUG false
#ifdef _DEBUG
#define Print(s) printf(s);
#endif
Getting Error:
error: '#' is not followed by a macro parameter
Any suggestion how to achieve this with pre-processor directives?
I intend to use it from my main as:
DEBUG(true);
Print("Inside main in debug mode");
You cannot redefine a MACRO at run-time.
Neither you can have a #define inside of another #define, like you try in the first line of your code.
You can do something like this:
#ifdef _DEBUG
#define Print(s) printf("%s", s)
#else
#define Print(s)
#endif
And use it from your main as:
#define _DEBUG
Print("Inside main in debug mode");
#undef _DEBUG
Print("Inside main debug mode off");
If you really need to switch debug on and off at run-time, your can do something like this:
void PrintIf(BOOL dbg, char * msg)
{
if (dbg)
{
printf("%s", msg)
}
}
And use it like this
y = TRUE;
PrintIf(y,"Inside main in debug mode");
y = FALSE;
PrintIf(y,"Inside main debug mode off");
Try this:
#ifdef DEBUG
#define Print(s) printf("%s", s)
#else
#define Print(s)
#endif
Then:
#define DEBUG
Print("Inside main in debug mode");
I intend to use it from my main as:
DEBUG(y);
Print("Inside main in debug mode");
Sorry, but ifdef are compile time (not run-time). You could use a global bool and runtime checking to enable and disable debug.
You can't create preprocessor statements with macros as you are trying to do; it doesn't work and isn't allowed. For conditional printing, see C #define macro for debug printing.
The problem occurs here:
#define DEBUG(y) y == true ? #define _DEBUG true : #define _DEBUG false
When introducing #defines, the definition # occurs at the beginning of the line, not later (although) preprocessors generally allow one or two line indents.) You need to rewrite your #define eliminating the ternary operator simply as:
#ifdef _DEBUG
#define Print(s) printf(s);
#endif
While you may extend you defines with macros, you often introduce additional errors. It is generally better to stick to wrapping your _DEBUG code simply in #ifdef statements:
#ifdef _DEBUG
fprintf (stderr, "your error messages\n"); // using standard printf/fprintf instead of macros
...
#endif /* _DEBUG */
Macros are substituted at preprocessing stage and
#define DEBUG(y) y == true ? #define _DEBUG true : #define _DEBUG false
this statement will be evaluated at compile time.
Conditional operator (ternary operator) are evaluated at compile time. So you are getting this error and # operator must always be used at the beginning of the statement that is the second mistake you are doing.
You can better use it this way
#define DEBUG
printf ("true");
#else
printf ("false");
You can also define this macro dynamically by using the gcc option -D
gcc -D DEBUG filename.c -o outputFile
The first line is incorrect:
#define DEBUG(y) y == true ? #define _DEBUG true : #define _DEBUG false
You cannot use #define inside preprocessor directive (like another #define)
And it does not make sense, since preprocessing happens before the real compilation (so before run time, when your y has some value). Read the cpp preprocessor documentation. Recall that sometimes the preprocessor is even a different program (/lib/cpp) but is today the first phase of most C compilers.
You could ask for the preprocessed form of your source code (e.g. with gcc -C -E source.c > source.i if using GCC) and look at that form with a pager (less source.i) or your editor.
I'm trying to do a debug system but it seems not to work.
What I wanted to accomplish is something like this:
#ifndef DEBUG
#define printd //
#else
#define printd printf
#endif
Is there a way to do that? I have lots of debug messages and I won't like to do:
if (DEBUG)
printf(...)
code
if (DEBUG)
printf(...)
...
No, you can't. Comments are removed from the code before any processing of preprocessing directives begin. For this reason you can't include comment into a macro.
Also, any attempts to "form" a comment later by using any macro trickery are not guaranteed to work. The compiler is not required to recognize "late" comments as comments.
The best way to implement what you want is to use macros with variable arguments in C99 (or, maybe, using the compiler extensions).
A common trick is to do this:
#ifdef DEBUG
#define OUTPUT(x) printf x
#else
#define OUTPUT(x)
#endif
#include <stdio.h>
int main(void)
{
OUTPUT(("%s line %i\n", __FILE__, __LINE__));
return 0;
}
This way you have the whole power of printf() available to you, but you have to put up with the double brackets to make the macro work.
The point of the double brackets is this: you need one set to indicate that it's a macro call, but you can't have an indeterminate number of arguments in a macro in C89. However, by putting the arguments in their own set of brackets they get interpreted as a single argument. When the macro is expanded when DEBUG is defined, the replacement text is the word printf followed by the singl argument, which is actually several items in brackets. The brackets then get interpreted as the brackets needed in the printf function call, so it all works out.
ะก99 way:
#ifdef DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...)
#endif
Well, this one doesn't require C99 but assumes compiler has optimization turned on for release version:
#ifdef DEBUG
#define printd printf
#else
#define printd if (1) {} else printf
#endif
On some compilers (including MS VS2010) this will work,
#define CMT / ## /
but no grantees for all compilers.
You can put all your debug call in a function, let call it printf_debug and put the DEBUG inside this function.
The compiler will optimize the empty function.
The standard way is to use
#ifndef DEBUG
#define printd(fmt, ...) do { } while(0)
#else
#define printd(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
That way, when you add a semi-colon on the end, it does what you want.
As there is no operation the compiler will compile out the "do...while"
Untested:
Edit: Tested, using it by myself by now :)
#define DEBUG 1
#define printd(fmt,...) if(DEBUG)printf(fmt, __VA_ARGS__)
requires you to not only define DEBUG but also give it a non-zer0 value.
Appendix:
Also works well with std::cout
In C++17 I like to use constexpr for something like this
#ifndef NDEBUG
constexpr bool DEBUG = true;
#else
constexpr bool DEBUG = false;
#endif
Then you can do
if constexpr (DEBUG) /* debug code */
The caveats are that, unlike a preprocessor macro, you are limited in scope. You can neither declare variables in one debug conditional that are accessible from another, nor can they be used at outside function scopes.
You can take advantage of if. For example,
#ifdef debug
#define printd printf
#else
#define printd if (false) printf
#endif
Compiler will remove these unreachable code if you set a optimization flag like -O2. This method also useful for std::cout.
As noted by McKay, you will run into problems if you simply try to replace printd with //. Instead, you could use variadric macros to replace printd with a function that does nothing as in the following.
#ifndef DEBUG
#define printd(...) do_nothing()
#else
#define printd(...) printf(__VA_ARGS__)
#endif
void do_nothing() { ; }
Using a debugger like GDB might help too, but sometimes a quick printf is enough.
I use this construct a lot:
#define DEBUG 1
#if DEBUG
#if PROG1
#define DEBUGSTR(msg...) { printf("P1: "); printf( msg); }
#else
#define DEBUGSTR(msg...) { printf("P2: "); printf( msg); }
#endif
#else
#define DEBUGSTR(msg...) ((void) 0)
#endif
This way I can tell in my console which program is giving which error message... also, I can search easily for my error messages...
Personally, I don't like #defining just part of an expression...
It's been done. I don't recommend it. No time to test but the mechanism is kind of like this:
#define printd_CAT(x) x ## x
#ifndef DEBUG
#define printd printd_CAT(/)
#else
#define printd printf
#endif
This works if your compiler processes // comments in the compiler itself (there's no guarantee like the ANSI guarantee that there are two passes for /* comments).