What does a #define directive without an argument do? - c

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_

Related

Why only define a macro if it's not already defined?

All across our C code base, I see every macro defined the following way:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
What is the rationale of doing these define checks instead of just defining the macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
I can't find this practice explained anywhere on the web.
This allows you to override the macros when you're compiling:
gcc -DMACRONAME=value
The definitions in the header file are used as defaults.
As I said in the comment, imagine this situation:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Will print 44.
However, if the conditional ifndef was not there, the result would be compilation warnings of MACRO redefinition and it will print 64.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
I do not know the context but this can be used to give the user the availability to override the values set by those macro definitions. If the user explicitly defines a different value for any of those macros it will be used instead of the values used here.
For instance in g++ you can use the -D flag during compilation to pass a value to a macro.
This is done so that the user of the header file can override the definitions from his/her code or from compiler's -D flag.
Any C project resides on multiple source files. When working on a single source file the checks seem to (and actually) have no point, but when working on a large C project, it's a good practice to check for existing defines before defining a constant. The idea is simple: you need the constant in that specific source file, but it may have been already defined in another.
You could think about a framework/library that gives to the user a default preset that allow the user to compile and work on it.
Those defines are spreaded in different files and the final user is advised to include it's config.h file where he can config its values.
If the user forgot some define the system can continue to work because of the preset.
Using
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
allows the user to define the value of the macro using the command line argument (in gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.
There is another important reason. It is an error to re-define a preprocessor macro differently. See this answer to another SO question. Without the #ifndef check, the compiler should produce an error if -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f is used as a command line argument in the compiler invocation.

#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

Is there a way to both check a macro is defined and it equals a certain value at the same time

I regularly use object-like preprocessor macros as boolean flags in C code to turn on and off sections of code.
For example
#define DEBUG_PRINT 1
And then use it like
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
However, it comes a problem if the header file that contains the #define is forgotten to be included in the source code. Since the macro is not declared, the preprocessor treats it as if it equals 0, and the #if statement never runs.
When the header file is forgotten to be included, non-expected, unruly behaviour can occur.
Ideally, I would like to be able to both check that a macro is defined, and check that it equals a certain value, in one line. If it is not defined, the preprocessor throws an error (or warning).
I'm looking for something along the lines of:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
It's like a combination of #ifdef and #if, and if it doesn't exist, uses #error.
I have explored a few avenues, however, preprocessor directives can't be used inside a #define block, and as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
This may not work for the general case (I don't think there's a general solution to what you're asking for), but for your specific example you might consider changing this sequence of code:
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
to:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
It's no more verbose and will fail to compile if DEBUG_PRINT is not defined or if it's defined to be something that cannot be compared with 1.
as far as I can tell, there is no preprocessor option to throw errors/warnings if a macro is not defined when used inside a #if statement.
It can't be an error because the C standard specifies that behavior is legal. From section 6.10.1/3 of ISO C99 standard:
After all replacements due to macro expansion and the defined unary
operator have been performed, all remaining identifiers are replaced with the pp-number
0....
As Jim Balter notes in the comment below, though, some compilers (such as gcc) can issue warnings about it. However, since the behavior of substituting 0 for unrecognized preprocessor tokens is legal (and in many cases desirable), I'd expect that enabling such warnings in practice would generate a significant amount of noise.
There's no way to do exactly what you want. If you want to generate a compilation failure if the macro is not defined, you'll have to do it explicitly
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
for each source file that cares. Alternatively, you could convert your macro to a function-like macro and avoid using #if. For example, you could define a DEBUG_PRINT macro that expands to a printf call for debug builds but expands to nothing for non-debug builds. Any file that neglects to include the header defining the macro then would fail to compile.
Edit:
Regarding desirability, I have seen numerous times where code uses:
#if ENABLE_SOME_CODE
...
#endif
instead of:
#ifdef ENABLE_SOME_CODE
...
#endif
so that #define ENABLE_SOME_CODE 0 disables the code rather than enables it.
Rather than using DEBUG_PRINT directly in your source files, put this in the header file:
#if !defined(DEBUG_PRINT)
#error DEBUG_PRINT is not defined
#endif
#if DEBUG_PRINT
#define PrintDebug([args]) [definition]
#else
#define PrintDebug
#endif
Any source file that uses PrintDebug but doesn't include the header file will fail to compile.
If you need other code than calls to PrintDebug to be compiled based on DEBUG_PRINT, consider using Michael Burr's suggestion of using plain if rather than #if (yes, the optimizer will not generate code within a false constant test).
Edit:
And you can generalize PrintDebug above to include or exclude arbitrary code as long as you don't have commas that look like macro arguments:
#if !defined(IF_DEBUG)
#error IF_DEBUG is not defined
#endif
#if IF_DEBUG
#define IfDebug(code) code
#else
#define IfDebug(code)
#endif
Then you can write stuff like
IfDebug(int count1;) // IfDebug(int count1, count2;) won't work
IfDebug(int count2;)
...
IfDebug(count1++; count2++;)
Yes you can check both:
#if defined DEBUG && DEBUG == 1
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
In this example even when #define DEBUG 0 but it is not equal to 1 thus nothing will be printed.
You can do even this:
#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
Here if you #define DEBUG 0 and then D(1,2,3) also nothing will be printed
DOC
Simply create a macro DEBUG_PRINT that does the actual printing:
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
If the macro isn't defined, then you will get a compiler error because the symbol is not recognized.
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
So when "if 0" it'll do nothing and when "if 1" it'll execute the defined macro.

redefining a constant in C

If I have a constant defined as such in a header file:
#define MY_CONSTANT 1
And I include a library to the whole project which includes a different definition for the same constant:
#define MY_CONSTANT 0
I naturally get conflicts while compiling. Supposing that I cannot alter my project code and that I can only change my library code, what can I do to make MY_CONSTANT as defined by my lib?
EDIT:
just to clarify, my goal is to update a constant in my code through a library. Because I'm writing a library to simulate hardware functions, I have to go by the rule that the software itself must be untouched. There is a loop of sort in the main file that uses the constant. I need to change this constant, but without actually altering it in the main file.
You can undefine the other definition
#ifdef MY_CONSTANT
#undef MY_CONSTANT
#endif
#define MYCONSTANT 0
Also, you should remove the =, and the ;
P.S. as mentioned, it will not change the code that already compiled.
You can #undef MY_CONSTANT and redefine to the value you want, but that's just asking for trouble. See if you can modify the design entirely so that MY_CONSTANTs don't clash.
Undef, redef, and then redef it back
#ifdef MY_CONSTANT
#undef MY_CONSTANT
#endif
#define MY_CONSTANT 0
/* code here */
#undef MY_CONSTANT /* not needed if you don't need the library's definition*/
#include "library.h" /* file that originally defined it
might not work if include guards prevent it
in that case #undef LIBRARY_H
although that causes more trouble :( */

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.

Resources