Conditionally use #warning or #pragma message or nothing - c-preprocessor

I have a code which uses #warning a lot to signal compile time branches to the user. The code has a lot of configuration option, therefore it is not really clear which bits of the code are actually taken into the compilation.
Once you have chosen the configuration options, those warnings really clutter the output. So I would like to be able to disable them. The easiest way would be wrapping each of those warnings into an #ifdef ... #else construct. But if I was to touch that code again, I need to go through the whole codebase again.
So instead I want to abstract this a bit. However, I am stuck trying to define a macro that calls #warning or #pragma message. The following compiles but does not do the right thing:
#ifdef EMIT_WARNINGS
#define WARNING(s) _Pragma("message(\"Hi\")")
#else
#define WARNING(s)
#endif
WARNING("How can I print this?")
All my attempts of putting s into there have failed. Once I do _Pragma("message(\"" s "\")"), I get that _Pragma expects a single parenthesised string.
Is there anything I can do to abstract this nicely?

All my attempts of putting s into there have failed. Once I do _Pragma("message(\"" s "\")"), I get that _Pragma expects a single parenthesised string.
_Pragma(S) has an effect equivalent to #pragma X, where X is the unstringified form of S. Going backwards, that means that to get the effect of #pragma X in a _Pragma call, you simply need to stringify X.
The fact that part of X is itself a string is misleading you... don't think of these as pieces you're assembling, but rather as a whole. Rather than trying to stringify s and put it inside "message(\"" and "\")", just stringify message(s) itself as a whole, like this:
#ifdef EMIT_WARNINGS
#define WARNING_I(s) _Pragma(#s)
#define WARNING(s) WARNING_I(message(s))
#else
#define WARNING(s)
#endif
WARNING("How can I print this?")
So when warnings are enabled, WARNING("How can I print this?") expands to WARNING_I(message("How can I print this")). That argument to WARNING_I is itself what you would put on a pragma line; it is your X. The definition of WARNING_I then stringifies that, making the correct S for _Pragma.

From https://gcc.gnu.org/onlinedocs/gcc-6.3.0/cpp/Diagnostics.html#Diagnostics
Neither ‘#error’ nor ‘#warning’ macro-expands its argument. Internal whitespace sequences are each replaced with a single space. The line must consist of complete tokens. It is wisest to make the argument of these directives be a single string constant; this avoids problems with apostrophes and the like.

Related

C variadic macro with two named parameters

I want to use a variadic macro but it appears to be designed to only treat the first parameter specially. I want the first two parameters to be named and the rest not, like so:
#define FOO(AA,BB,...) AA->BB(AA,##...)
FOO(mystruct,funcname,123)
However this is not working with LLVM. Am I doing something wrong, or is there a limitation to how the variadic macro works?
UPDATE
The correct answer is, use ##VA_ARGS instead of ##...
There are some webpages that claim that "..." is valid but at least with the MacOS llvm it is not.
The macro arguments are not expanded with ... in the macro expansion - how could they, because then you couldn't have a macro that used ellipsis in the expansion. Instead it will be available as a special parameter __VA_ARGS__.
With this, the following program
#define FOO(AA,BB,...) AA->BB(AA, __VA_ARGS__)
FOO(mystruct,funcname,123)
FOO(mystruct,funcname,123,456)
will be preprocessed to
The ## is a token-pasting operator. It will make a single preprocessing token out of 2 parts. , ## ... attempts to make a preprocessing token ,.... It is not a valid C token, and that is why Clang will report
<source>:3:1: error: pasting formed ',...', an invalid preprocessing token
... macro arguments are pasted into macro bodies with __VA_ARGS__.
The problem is how to allow for it to be empty.
If it is empty, you'll usually want to comma before it erased and
you can use the GNU ##__VA_ARGS__ extension to achieve that.
#define FOO(AA,BB,...) AA->BB(AA,##__VA_ARGS__) /*GNU extension*/
FOO(mystruct,funcname) //warning with -pedantic
FOO(mystruct,funcname,123)
The above, however, will trigger warnings if compiled with -pedantic.
If you want your macro usable without warnings at -pedantic, you could perhaps achieve that by swapping the first two arguments in the macro definition.
#define FIRST(...) FIRST_(__VA_ARGS__,)
#define FIRST_(X,...) X
#define BAR_(CallExpr,...) CallExpr(__VA_ARGS__)
#define BAR(BB,/*AA,*/...) BAR_(FIRST(__VA_ARGS__)->BB,__VA_ARGS__)
BAR(funcname,mystruct) //no warning
BAR(funcname,mystruct,123)

How to create a "C single-line comment" macro

I am trying to create a "single line comment" macro in C, this is used conditionally to comment out lines of codes, according to some global macro definitions. It is the same idea expressed in this article.
Trying many permutations of this code, I keep getting error messages from the compiler.
For example, directly following the code sample from that page:
#define COMMENT SLASH(/)
#define SLASH(s) /##s
#define DEBUG_ONLY COMMENT
DEBUG_ONLY a = b; // <-- line #83
GCC gives the following error:
prog.c:83:1: error: pasting "/" and "/" does not give a valid preprocessing token
prog.c:83: error: expected expression before ‘/’ token
As mentioned, I played with that theme and tried many variations but all fail giving similar diagnostics.
What am I doing wrong, and why doesn't the code from the article compiles well?
It doesn't work because the language specification doesn't allow it. In effect, comment removal happens before macro replacement. Once comments have been removed, // is not a valid token (like the error message says). It can't be generated by macro replacement, and it no longer means "comment".
This is "Translation phases" in the standard. The section numbering differs, but all of C89, C99 and C11 define in phase 3:
Each comment is replaced by one space character.
and then in phase 4:
macro invocations are expanded
A debug macro:
#define DEBUG(x) x
Which can be turned off in production as:
#define DEBUG(x)
Or IIRC #undef (sorry, my C is rusty).
Why not simply just use e.g.
#ifdef DEBUG
a = b;
#endif /* DEBUG */
Less trouble, and just as readable.
With a #define macro, you can't comment out an entire line per se, but you can comment out everything up to the next semi-colon. I find that this method works pretty well.
#define LOG_LVL 111100011
// 987654321
#if(LOG_LVL%10 >= 1 )
#define LOG1 if(1)
#else
#define LOG1 if(0)
#endif//End LOG1 if-block
#if(LOG_LVL%1000 >= 100)
#define LOG3 if(1)
#else
#define LOG3 if(0)
#endif//End LOG3 if-block
As long as you are careful with your semicolons, this should work fine. By default a non-braced if statement will only execute the following line.
The other benefit of doing logging like this is that you can fine tune what level of logging you want. In this example LOG1 is enabled and LOG3 is disabled. If i wanted my logging to be more verbose, i can quickly change LOG_LVL 111100011 to have a 1 (or higher) in it's 3 digit so that LOG3 will be enabled.
I used #define cout(x) //cout<<x; for my applications. You may want to modify it like
#ifdef DEBUG
#define cout(x) cout<<x;
#else
#define cout(x)
And use it as
cout(arg0<<arg1<<arg2);
Here, you won't be commenting the line and thus won't need separate line for avoiding print.
Further you can use cout wherever printing has to be done unconditionally.
cout("Print this when debugging");
cout<<"Always print this";

Proper C preprocessor macro no-op

For debug logging, I have often seen and used something like
#ifdef DEBUG
#define DLOG(fmt, args...) printf("%s:%d "fmt,__FILE__,__LINE__,args)
#else
#define DLOG(fmt, args...)
#endif
but in a number of places, I have seen the second #define replaced with
#define DLOG(fmt, args...) do {} while (0)
In particular, there's this answer, and the comment on this other answer to the same question suggests that the problem would be in a situation like
if (condition)
DLOG("foo");
though my quick test suggests that the resulting semicolon on the line by itself will serve as the no-op statement inside the conditional.
Is one or the other of nothing and do {} while (0) better? If so, why? Is there something else that's even better?
A semicolon by itself has two drawbacks:
Users of your macro can write it without a semicolon, and the compiler will not complain, and
Some compilers may issue a warning about a possibly stray semicolon.
The do {} while (0) trick addresses both these concerns:
DLOG("foo") // No semicolon
will trigger an error, and the compiler will not warn you about a "stray" semicolon.
See C #define macro for debug printing for an explanation of why you want a different form of no-op. You want to have the compiler parse the debug printing code even when you aren't using it so that errors do not creep in.
The quick answer is that the do/while method lets you have a multi-statement replacement and still use it as a single statement in an if case like you have in your question. For a single expression replacement, I don't think there's any difference.

Can a C macro definition refer to other macros?

What I'm trying to figure out is if something such as this (written in C):
#define FOO 15
#define BAR 23
#define MEH (FOO / BAR)
is allowed? I would want the preprocessor to replace every instance of
MEH
with
(15 / 23)
but I'm not so sure that will work. Certainly if the preprocessor only goes through the code once then I don't think it'd work out the way I'd like.
I found several similar examples but all were really too complicated for me to understand. If someone could help me out with this simple one I'd be eternally grateful!
Short answer yes. You can nest defines and macros like that - as many levels as you want as long as it isn't recursive.
The answer is "yes", and two other people have correctly said so.
As for why the answer is yes, the gory details are in the C standard, section 6.10.3.4, "Rescanning and further replacement". The OP might not benefit from this, but others might be interested.
6.10.3.4 Rescanning and further replacement
After all parameters in the replacement list have been substituted and
# and ## processing has taken place, all placemarker preprocessing tokens are removed.
Then, the resulting preprocessing token sequence
is rescanned, along with all subsequent preprocessing tokens of the
source file, for more macro names to replace.
If the name of the macro being replaced is found during this scan of
the replacement list (not including the rest of the source file's
preprocessing tokens), it is not replaced. Furthermore, if any nested
replacements encounter the name of the macro being replaced, it is not
replaced. These nonreplaced macro name preprocessing tokens are no
longer available for further replacement even if they are later
(re)examined in contexts in which that macro name preprocessing token
would otherwise have been replaced.
The resulting completely macro-replaced preprocessing token sequence
is not processed as a preprocessing directive even if it resembles
one, but all pragma unary operator expressions within it are then
processed as specified in 6.10.9 below.
Yes, it's going to work.
But for your personal information, here are some simplified rules about macros that might help you (it's out of scope, but will probably help you in the future). I'll try to keep it as simple as possible.
The defines are "defined" in the order they are included/read. That means that you cannot use a define that wasn't defined previously.
Usefull pre-processor keyword: #define, #undef, #else, #elif, #ifdef, #ifndef, #if
You can use any other previously #define in your macro. They will be expanded. (like in your question)
Function macro definitions accept two special operators (# and ##)
operator # stringize the argument:
#define str(x) #x
str(test); // would translate to "test"
operator ## concatenates two arguments
#define concat(a,b) a ## b
concat(hello, world); // would translate to "helloworld"
There are some predefined macros (from the language) as well that you can use:
__LINE__, __FILE__, __cplusplus, etc
See your compiler section on that to have an extensive list since it's not "cross platform"
Pay attention to the macro expansion
You'll see that people uses a log of round brackets "()" when defining macros. The reason is that when you call a macro, it's expanded "as is"
#define mult(a, b) a * b
mult(1+2, 3+4); // will be expanded like: 1 + 2 * 3 + 4 = 11 instead of 21.
mult_fix(a, b) ((a) * (b))
Yes, and there is one more advantage of this feature. You can leave some macro undefined and set its value as a name of another macro in the compilation command.
#define STR "string"
void main() { printf("value=%s\n", VALUE); }
In the command line you can say that the macro "VALUE" takes value from another macro "STR":
$ gcc -o test_macro -DVALUE=STR main.c
$ ./test_macro
Output:
value=string
This approach works as well for MSC compiler on Windows. I find it very flexible.
I'd like to add a gotcha that tripped me up.
Function-style macros cannot do this.
Example that doesn't compile when used:
#define FOO 1
#define FSMACRO(x) FOO + x
Yes, that is supported. And used quite a lot!
One important thing to note though is to make sure you paranthesize the expression otherwise you might run into nasty issues!
#define MEH FOO/BAR
// vs
#define MEH (FOO / BAR)
// the first could be expanded in an expression like 5 * MEH to mean something
// completely different than the second

Preprocessor on C

I added this in my code:
#ifdef DEBUG_MODE
printf("i=%d\n",i);
fflush(stdout);
#endif
and my question is, if I'm not in DEBUG_MODE what the compiler does when compiling this?
The compiler will do nothing, because there will be nothing there when DEBUG_MODE is not defined.
#ifdef and #endif control conditional compilation. This happens during an initial pass over the program, making dumb textual substitutions before the compiler even begins to consider the file to contain C code specifically. In this case, without the symbol defined only whitespace is left. The text is never even lexed into C tokens if the preprocessor define tested for isn't defined at that point.
You can see this for yourself: just invoke your compiler with whatever flag it uses to stop after preprocessing - e.g. gcc -E x.cc - and at that point in the output there will just be an empty line or two. This is also a very important technique for understanding macros, and a good thing to do when you just can't guess why some program's not working the way you expect - the compiler says some class or function doesn't exist and you've included its header - look at the preprocessed output to know what your compiler is really dealing with.
if DEBUG_MODE is not defined, the code under it will not be compiled.

Resources