Dealing with constants inside functions - c

I want to define a constant if something is true, and use its value inside a "system("");
For example:
#ifdef __unix__
# define CLRSCR clear
#elif defined _WIN32
# define CLRSCR cls
#endif
int main(){
system("CLRSCR"); //use its value here.
}
I know there is clrscr(); in conio.h/conio2.h but this is just an example. And when I try to launch it, it says cls is not declared, or that CLRSCR is not a internal command (bash)
Thanks

Constant is an identifier, not a string literal (string literals have double quotes around them; identifiers do not).
Constant value, on the other hand, is a string literal, not an identifier. You need to switch it around like this:
#ifdef __unix__
# define CLRSCR "clear"
#elif defined _WIN32
# define CLRSCR "cls"
#endif
int main(){
system(CLRSCR); //use its value here.
}

You need this:
#ifdef __unix__
#define CLRSCR "clear"
#elif defined _WIN32
#define CLRSCR "cls"
#endif
system(CLRSCR); //use its value here.

Related

Enable/Disable LOG levels using C Macro

#include <stdio.h>
#define LOG_D(x) { printf("D:"); printf(x);}
#define LOG_E(x) { printf("E:"); printf(x);}
void test(void)
{
LOG_D("ALL is well " );
}
I have a very huge code it has different levels of log, like above code.
In the final tested library I just need only one error logs in order to reduce the code size .
so I want something like this
#define ENABLE_DEBUG_LOG 0
#define ENABLE_ERROR_LOG 1
#define LOG_D(x) {#if(ENABLE_DEBUG_LOG==1) printf("D:"); printf(x); #endif}
#define LOG_E(x) {#if(ENABLE_ERROR_LOG==1) printf("E:"); printf(x);#endif}
I added this #if(ENABLE_DEBUG_LOG==1) just for explaining, I need some solution which can compile.
Another option - you can just comment / uncomment ENABLE_DEBUG_LOG and ENABLE_ERROR_LOG to disable / enable corresponding log level.
// #define ENABLE_DEBUG_LOG // disable DEBUG_LOG
#define ENABLE_ERROR_LOG // enable ERROR_LOG
#ifdef ENABLE_DEBUG_LOG
#define LOG_D(x) { printf("D:"); printf(x);}
#else
#define LOG_D(x) // nothing
#endif
#ifdef ENABLE_ERROR_LOG
#define LOG_E(x) { printf("E:"); printf(x);}
#else
#define LOG_E(x) // nothing
#endif
You cannot nest preprocessor directives. But you can make two versions of your macro and define them in exclusive parts of an #if or #ifdef:
#define ENABLE_DEBUG_LOG 0
#if ENABLE_DEBUG_LOG != 0
#define LOG_D(...) printf("D: " __VA_ARGS__)
#else
#define LOG_D(...) // Do nothing
#endif
Here, the disabled version just "eats" the LOG_D macro and doesn't do anything. (Note that undefined macros are treated as the value 0 in #if conditionals.)
You should be able to do something like this:
#if ENABLE_DEBUG_LOG == 1
# define LOG_D(x) { printf("D:"); printf(x);}
#else
# define LOG_D(x)
#end
That way the debug log statements will just disappear if ENABLE_DEBUG_LOG is undefined or has a different value.
Regarding the other answers, it is not good idea to define the macros completely empty when they are not enabled, as this would go wrong when error logging is enabled:
if (some_error)
LOG_E("Oops...");
do_something();
If LOG_E(x) expands to nothing, then do_something() would only be called if some_error is true, which is probably not what you want!
So you could define the "do nothing" variant of LOG_E(x) like this:
#define LOG_E(x) { }
Rather than starting and ending with braces, I tend to use the do { blah; } while (0) construct as it forces you to put a semicolon on the end when you use it. Something like this:
#if ENABLE_ERROR_LOG
#define LOG_E(x) do { printf("E:"); printf(x); } while (0)
#else
#define LOG_E(x) do ; while (0)
#endif
Then,
if (some_error)
LOG_E("Oops")
would result in a syntax error because of the missing semicolon, forcing you to write it as
if (some_error)
LOG_E("Oops");
Another thing you can do is concatenate the "E:" or "D:" tag with the passed in string, although this requires the parameter to be a string literal, rather than a general char *:
#define LOG_E(x) printf("E:" x)
Another thing you can do is to define the macro with a variable number of parameters (a variadic macro) to increase your options:
#define LOG_E(...) printf("E:" __VA_ARGS__)
Then you can do:
if (some_error)
LOG_E("Oops, got error: %d\n", some_error);
Another thing you can do is let the compiler optimize out the call to printf and define it like this:
#define LOG_E(...) do if (ENABLE_ERROR_LOG) printf("E:" __VA_ARGS__); while (0)
A decent compiler will notice that the if condition is constant and either optimize out the call to printf completely (if the constant condition is false), or include it (if the constant condition is true). For some compilers, you might need to suppress warnings about constant conditions in an if statement.
I am not sure if this is what you want, but you could check the #ifdef directive.
#include <stdio.h>
/* #define DEBUG */
#ifdef DEBUG
#define LOG_D(x) { printf("D: %s\n",x); }
#define LOG_E(x) { printf("E: %s\n",x); }
#else
#define LOG_D(x)
#define LOG_E(x)
#endif
int main() {
LOG_D("blah...");
return 0;
}
If you uncomment the #define DEBUG line, the program will print D: blah...

What does a #define directive without an argument do?

On Apple's opensource website, the entry for stdarg.h contains the following:
#ifndef _STDARG_H
#ifndef _ANSI_STDARG_H_
#ifndef __need___va_list
#define _STDARG_H
#define _ANSI_STDARG_H_
#endif /* not __need___va_list */
#undef __need___va_list
What do the #define statements do if there's nothing following their first argument?
There are sort of three possible "values" for an identifier in the preprocessor:
Undefined: we don't know about this name.
Defined, but empty: we know about this name, but it has no value.
Defined, with value: we know about this name, and it has a value.
The second, defined but empty, is often used for conditional compilation, where the test is simply for the definedness, but not the value, of an identifier:
#ifdef __cplusplus
// here we know we are C++, and we do not care about which version
#endif
#if __cplusplus >= 199711L
// here we know we have a specific version or later
#endif
#ifndef __cplusplus // or #if !defined(__cplusplus)
// here we know we are not C++
#endif
That's an example with a name that if it is defined will have a value. But there are others, like NDEBUG, which are usually defined with no value at all (-DNDEBUG on the compiler command line, usually).
They define a macro which expands to nothing. It's not very useful if you intended it to be used as a macro, but it's very useful when combined with #ifdef and friends—you can, for example, use it to create an include guard, so when you #include a file multiple times, the guarded contents are included only once.
You define something like:
#define _ANSI_STDARG_H_
so that, later you can check for:
#ifdef _ANSI_STDARG_H_

#define IDENTIFIER without a token

What does the following statement mean:
#define FAHAD
I am familiar with the statements like:
#define FAHAD 1
But what does the #define statement without a token signify?
Is it that it is similar to a constant definition?
Defining a constant without a value acts as a flag to the preprocessor, and can be used like so:
#define MY_FLAG
#ifdef MY_FLAG
/* If we defined MY_FLAG, we want this to be compiled */
#else
/* We did not define MY_FLAG, we want this to be compiled instead */
#endif
it means that FAHAD is defined, you can later check if it's defined or not with:
#ifdef FAHAD
//do something
#else
//something else
#endif
Or:
#ifndef FAHAD //if not defined
//do something
#endif
A real life example use is to check if a function or a header is available for your platform, usually a build system will define macros to indicate that some functions or headers exist before actually compiling, for example this checks if signal.h is available:
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif/*HAVE_SIGNAL_H*/
This checks if some function is available
#ifdef HAVE_SOME_FUNCTION
//use this function
#else
//else use another one
#endif
Any #define results in replacing the original identifier with the replacement tokens. If there are no replacement tokens, the replacement is empty:
#define DEF_A "some stuff"
#define DEF_B 42
#define DEF_C
printf("%s is %d\n", DEF_A, DEF_B DEF_C);
expands to:
printf("%s is %d\n", "some stuff", 42 );
I put a space between 42 and ) to indicate the "nothing" that DEF_C expanded-to, but in terms of the language at least, the output of the preprocessor is merely a stream of tokens. (Actual compilers generally let you see the preprocessor output. Whether there will be any white-space here depends on the actual preprocessor. For GNU cpp, there is one.)
As in the other answers so far, you can use #ifdef to test whether an identifier has been #defined. You can also write:
#if defined(DEF_C)
for instance. These tests are positive (i.e., the identifier is defined) even if the expansion is empty.
#define FAHAD
this will act like a compiler flag, under which some code can be done.
this will instruct the compiler to compile the code present under this compiler option
#ifdef FAHAD
printf();
#else
/* NA */
#endif

C: Preprocessor in Macros?

Is there a way to use preprocessor keywords inside of a macro? If there is some sort of escape character or something, I am not aware of it.
For example, I want to make a macro that expands to this:
#ifdef DEBUG
printf("FOO%s","BAR");
#else
log("FOO%s","BAR");
#endif
from this:
PRINT("FOO%s","BAR");
Is this possible, or am I just crazy (and I will have to type out the preprocessor conditional every time I want to show a debug message)?
You can't do that directly, no, but you can define the PRINT macro differently depending on whether DEBUG is defined:
#ifdef DEBUG
#define PRINT(...) printf(__VA_ARGS__)
#else
#define PRINT(...) log(__VA_ARGS__)
#endif
Just do it the other way around:
#ifdef DEBUG
#define PRINT printf
#else
#define PRINT log
#endif
You're not crazy, but you're approaching this from the wrong angle. You can't have a macro expand to have more preprocessor arguments, but you can conditionally define a macro based on preprocessor arguments:
#ifdef DEBUG
# define DEBUG_PRINT printf
#else
# define DEBUG_PRINT log
#endif
If you have variadic macros, you could do #define DEBUG_PRINTF(...) func(__VA_ARGS__) instead. Either way works. The second lets you use function pointers, but I can't imagine why you'd need that for this purpose.

Can you #define a comment in C?

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).

Resources