Define with only 1 argument - c

I'm reading external C code, and I found the following line of code:
#define __MAIN_C__
where #define is given only one "argument" (namely __MAIN_C__).
Is this just a placeholder, or can it have a function?

That #define will define __MAIN_C__ to no value (thanks to n.m. and a simple test program). It's a shortcut when you need something #defined when you don't care what it's defined to. In that case, somewhere in your code, you'd probably just see:
#ifdef __MAIN_C__
And that doesn't care what specific value it has, as long as it's defined (and perhaps nonzero).
You'll very often see this for include guards, like so:
#ifndef MYHEADER_H
#define MYHEADER_H
// stuff here
#endif
This is similar to doing this in the compile flags:
gcc -D__MAIN_C__ main.c
If you want to see that it's defined to nothing, try to compile this and watch it fail:
#include <stdio.h>
#define TEST
int main(int argc, char *argv[])
{
printf("%d\n", TEST);
return 0;
}

Yes, this can accomplish something. If you look, there's a pretty decent chance you'll find something like: #ifdef __MAIN_C__ somewhere -- this just checks whether the symbol has been defined, regardless of the value (if any) given.

A define in this case simply sets MAIN_C. No value is assigned, but the preprocessor will interperet MAIN_C as "true". Generally, defines like these are used to include or exclude code before compilation, using something like the following:
#define WIN32
#ifdef WIN32
//some win32-specific code
#else
//some other code
#endif

This definition makes __MAIN_C__ to expand (roughly speaking) to nothing.
A possible use:
#ifdef __MAIN_C__
foo(bar);
#endif
Another one:
#ifdef PLAIN_OLD_OS
#define __MAIN_C__
#else
#define __MAIN_C__ __os_specific_attribute(dllsomething)
#endif
__MAIN_C__ int main (int argc, char* argv[]) {

Related

Using macro statement in macro function in C

Using #ifdef <macro> <statement> #endif allows one to have verbose messages displayed only during development and is quite handy. I wonder if something like the code below is possible, becoming even shorter:
// pseudo-code:
#define IN_DEV
#define DEBUG_ONLY(statement) (#ifdef IN_DEV (statement) #endif)
int main(void)
{
DEBUG_ONLY(printf("hello from debug mode\n");)
//...
}
This would only cost me a very readable one-liner which can be turned on or off. Is something like this / close to this possible?
You could change the meaning of DEBUG_ONLY dependent on if IN_DEV is defined:
// pseudo-code:
#ifdef IN_DEV
#define DEBUG_ONLY(statement) {statement}
#else
#define DEBUG_ONLY(statement) // Nothing
#endif
int main(void)
{
DEBUG_ONLY(printf("hello from debug mode\n");)
//...
}
Running example: Link
It doesn't make much sense to pass whole expressions as parameters to macros. That is both dangerous and unmaintainable. Worse yet, it's taking us down the obfuscation road of "lets invent our own private macro language instead of using readable C that anyone can understand". That's a terrible idea even for debugging purposes.
The more sensible approach would be a function-like printing macro which only prints something in debug build.
#ifdef INDEV
#define DEBUG_PRINT(...) printf(__VA_ARGS__)
#else
#define DEBUG_PRINT(...)
#endif
int main(void)
{
DEBUG_PRINT("hello from debug mode\n");
}
Optionally this macro can be narrowed down to only accept strings and be made more type safe (C17 only):
#ifdef INDEV
#define DEBUG_PRINT(str) _Generic((str), char*: puts(str))
#else
#define DEBUG_PRINT(str) _Generic((str), char*: (void)0)
#endif
That is not possible. You cannot use #if inside a macro definition.
What you can do is this:
#define IN_DEV
#ifdef
#define DEBUG_ONLY(statement) (statement)
#else
#define DEBUG_ONLY(statement)
#endif
int main(void)
{
DEBUG_ONLY(printf("hello from debug mode\n");)
//...
}
This is also switchable with only a single macro IN_DEV.

C define macro that expands not the same when not used for the first time

Is it possible to write:
#define FIRST_DEF 1
#define SECOND_DEF 2
#ifndef ALREADY_DEFINED
#define MY_MACRO FIRST_DEF
#define ALREADY_DEFINED
#else
#define MY_MACRO SECOND_DEF
#endif
So that MY_MACRO does not have the same value when not used the first time?
So that writting:
int a = MY_MACRO;
int b = MY_MACRO;
expands to:
int a = 1;
int b = 2;
If not, is there a way to do this?
(I know that this example is silly but it is just to make the question clearer.)
For your example, you can use the pre-defined macro __COUNTER__ which will get incremented everytime it is used. Note that it is a non-standard compiler extension, but both GCC and MSVC support it.
Yes. I think it is OK.
#include "xxx.h"
// FIRST_DEF here
#include "xxx.h"
// SeCOND_DEF here
But you must include the header twice

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 constant inside #ifdef in C

I want to define a constant depending on the OS in use.
As such:
#include <stdio.h>
#ifdef _Win32 //Used for system("cls") command
#include <process.h>
#define CLEAR "system(\"cls\")"
#endif
#ifdef __APPLE__
#define CLEAR "system(\"clear\")"
#endif
int main()
{
CLEAR;
}
Xcode gives me an error stating that expression result unused at
#define CLEAR "system(\"clear\") and inside the main function.
I am on a Mac.
Use:
#define CLEAR system("clear")
not
#define CLEAR "system(\"clear\")"
You get the error because your macro call is substituted with:
"system(\"clear\")";
which is a useless expression statement (the expression being the string here) like for example:
0; // valid but pointless
try altering your main function as such:
int main()
{
int rc;
rc = CLEAR;
return rc;
}
You need to catch the return value of the system() call and use it
#define CLEAR system("clear")
and not
#define CLEAR "system(\"clear\")"
The compiler will create a new C code (called pre-processor code) in which will replace the macro name by its content.
so if you define macro in this way:
#define CLEAR "system(\"clear\")"
You will get in the new code (pre-processor code) generated by the Compiler:
int main()
{
"system(\"clear\")";
}
You can see the code generated by the compiler (pre-processor code) with gcc -E

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