I've been using C for a little over a year now, and I was wondering exactly how #define
works.
I know you can use it as a macro, eg. #define MUL(x, y) (x*y)
, but what's happening when you define something without giving a definition?
e.g.
#ifndef _SYNNOVESLIB_H
#define _SYNNOVESLIB_H
#endif
Does it just get marked as "defined", or true (as in 1) by GCC or whatever compiler is being used?
#define _SYNNOVESLIB_H
tells the compiler to replace _SYNNOVESLIB_H
with nothing. It will be true for the purposes of things which check whether a macro is defined such as defined
, #ifdef
, and #ifndef
.
It can also be handy for conditionally defining certain features for compatibility. Here's an example in Perl 5.
6.10 Preprocessing directives provides the grammar for #define
.
control-line:
# define identifier replacement-list new-line
replacement-list:
pp-tokens(opt)
pp-tokens:
preprocessing-token
pp-tokens preprocessing-token
replacement-list
is an optional list of pre-processor tokens, so it can be empty.
From 6.10.1 Conditional inclusion
- The expression that controls conditional inclusion shall be an integer constant expression except that: identifiers (including those lexically identical to keywords) are interpreted as described below;169) and it may contain unary operator expressions of the form
defined identifier
or
defined ( identifier )
which evaluate to 1 if the identifier is currently defined as a macro name (that is, if it is predefined or if it has been the subject of a #define preprocessing directive without an intervening #undef directive with the same subject identifier), 0 if it is not.
Note that the value does not matter, simply that it has been defined.
- Preprocessing directives of the forms
# ifdef identifier new-line groupopt
or
# ifndef identifier new-line groupopt
check whether the identifier is or is not currently defined as a macro name. Their conditions are equivalent to
#if defined identifier
and#if !defined identifier
respectively.
Exactly how this is handled inside the compiler is up to the compiler, but a simple hash table would do. #define _SYNNOVESLIB_H
would add a key of _SYNNOVESLIB_H
with a null or empty value. #ifndef _SYNNOVESLIB_H
would check whether the key exists in the hash table, ignoring the value. #undef _SYNNOVESLIB_H
removes the key from the table.