macro which defines new macros with an added prefix - c++

We have a profiling framework which can be enabled and disabled at compile time.
All the various calls to the framework are done through macros, eg:
PROFILE_START(msg)
PROFILE_END(msg)
The macros then resolve to the actual profiler call when profiling is enabled, and to nothing when disabled
#ifdef PROFILING_ENABLED
# define PROFILE_START(msg) currentProfiler().start(msg)
# define PROFILE_END(msg) currentProfiler().end(msg)
#else
# define PROFILE_START(msg)
# define PROFILE_END(msg)
#endif
We have various different components in our framework, and I want to enable profiling in each component.
I'd like to be able to selectively enable profiling in each component.
My idea is to prefix all the profiler macros with the component's name, eg:
FOO_PROFILE_START(msg)
FOO_PROFILE_END(msg)
BAR_PROFILE_START(msg)
BAR_PROFILE_END(msg)
I could manually create
#ifdef ENABLE_FOO_PROFILING
# define FOO_PROFILE_START(msg) PROFILE_START(msg)
# define FOO_PROFILE_END(msg) PROFILE_END(msg)
#else
# define FOO_PROFILE_START(msg)
# define FOO_PROFILE_END(msg)
#endif
#ifdef ENABLE_BAR_PROFILING
# define BAR_PROFILE_START(msg) PROFILE_START(msg)
# define BAR_PROFILE_END(msg) PROFILE_END(msg)
#else
# define BAR_PROFILE_START(msg)
# define BAR_PROFILE_END(msg)
#endif
However, this is both tedious and error-prone.
Any time a new feature is added to the profiling framework I would have to find all my component specific macros and add a new macro to each of them.
What I'm looking for is a way to automatically generate the component-prefixed macros.
#ifdef ENABLE_FOO_PROFILING
ADD_PREFIX_TO_ENABLED_PROFILING_MACROS(FOO)
#else
ADD_PREFIX_TO_DISABLED_PROFILING_MACROS(FOO)
#endif
The net result of the above would be to create all the FOO_PROFILE_XXX macros I would have done manually.
Questions:
Is such a helper macro possible?
Is there a better way of achieving what I'm looking for?
I'm happy to use BOOST_PP if necessary.
Before posting this question I tried figuring this out myself, and the code I came up with follows, which may serve to show the road I was going down
#include <stdio.h>
#define PROFILE_START(msg) printf("start(%s)\n", msg);
#define PROFILE_END(msg) printf("end(%s)\n", msg);
#define ENABLE(prefix) \
#define prefix ## _PROFILE_START PROFILE_START \
#define prefix ## _PROFILE_END PROFILE_END
#define DISABLE(prefix) \
#define prefix ## _PROFILE_START \
#define prefix ## _PROFILE_END
#define ENABLE_FOO
#ifdef ENABLE_FOO
ENABLE(FOO)
#else
DISABLE(FOO)
#endif
#ifdef ENABLE_BAR
ENABLE(BAR)
#else
DISABLE(BAR)
#endif
int main()
{
FOO_PROFILE_START("foo");
FOO_PROFILE_END("foo");
BAR_PROFILE_START("bar");
BAR_PROFILE_END("bar");
return 0;
}

Is such a helper macro possible?
No. With the exception of pragmas, you cannot execute a preprocessing directive in a macro.
You can do something very similar using pattern matching. By taking the varying parts out of the macro name, and putting it inside the macro itself, you can make a form that allows enabling/disabling for arbitrary names.
This requires a tiny bit of preprocessor metaprogramming (which is a constant overhead; i.e., doesn't vary as you add modules), so bear with me.
Part 1: A C preprocessor solution
Using this set of macros:
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)
#define EAT(...)
#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)
...which you can include in each module, you will gain the ability to do this:
PROFILE_START_FOR(FOO,msg)
PROFILE_END_FOR(FOO,msg)
PROFILE_START_FOR(BAR,msg)
PROFILE_END_FOR(BAR,msg)
PROFILE_START_FOR(BAZ,msg)
PROFILE_END_FOR(BAZ,msg)
All of these macros, by default, expand to nothing; you can change this by defining ENABLE_PROFILER_FOR_xxx for any subset of FOO, BAR, or BAZ to expand to , (or ,ON if that looks better), in which case the corresponding macros will expand (initially, before your own macros come in) to PROFILE_START(msg)/PROFILE_END(msg); and the rest will continue expanding to nothing.
Using the FOO module as an example, you can do this with a "control file": #define ENABLE_PROFILER_FOR_FOO ,ON; the command line: ... -DENABLE_PROFILER_FOR_FOO=,ON; or in a makefile; CFLAGS += -DENABLE_PROFILER_FOR_FOO=,ON.
Part 2a: how it works; the SWITCH macro
#define GLUE(A,B) GLUE_I(A,B)
#define GLUE_I(A,B) A##B
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(_,X,...) X
#define SWITCH(PREFIX_,PATTERN_,DEFAULT_) SECOND(GLUE(PREFIX_,PATTERN_),DEFAULT_)
GLUE here is your typical indirect paste macro (allowing arguments to expand). SECOND is an indirect variadic macro returning the second argument.
SWITCH is the pattern matcher. The first two arguments are pasted together, comprising the pattern. By default, this pattern is discarded; but due to the indirection, if that pattern is an object like macro, and that pattern's expansion contains a comma, it will shift a new second argument in. For example:
#define ORDINAL(N_) GLUE(N_, SWITCH(ORDINAL_SUFFIX_,N_,th))
#define ORDINAL_SUFFIX_1 ,st
#define ORDINAL_SUFFIX_2 ,nd
#define ORDINAL_SUFFIX_3 ,rd
ORDINAL(1) ORDINAL(2) ORDINAL(3) ORDINAL(4) ORDINAL(5) ORDINAL(6)
...will expand to:
1st 2nd 3rd 4th 5th 6th
In this manner, the SWITCH macro behaves analogous to a switch statement; whose "cases" are object-like macros with matching prefixes, and which has a default value.
Note that pattern matching in the preprocessor works with shifting arguments, hence the comma (the main trick being that of discarding unmatched tokens by ignoring an argument, and applying matched tokens by shifting a desired replacement in). Also for the most general case with this SWITCH macro, you need at a minimum to ensure that all PREFIX_/PATTERN_ arguments are pasteable (even if that token isn't seen, it has to be a valid token).
Part 2b: combined switches for safety
A lone switch works like a case statement, allowing you to shove anything in; but when the situation calls for a binary choice (like "enable" or "disable"), it helps to nest one SWITCH in another. That makes the pattern matching a bit less fragile.
In this case, the implementation:
#define PROFILER_UTILITY(MODULE_) SWITCH(ENABLE_PROFILER_FOR_,MODULE_,DISABLED)
#define PROFILER_IS_DISABLED ,EAT
#define PROFILE_START_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START)(msg)
#define PROFILE_END_FOR(MODULE_, msg) SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_END)(msg)
...uses PROFILER_UTILITY as the inner switch. By default, this expands to DISABLED. That makes the pattern in SWITCH(PROFILER_IS_,PROFILER_UTILITY(MODULE_),PROFILE_START) by default be PROFILER_IS_DISABLED, which shoves in EAT. In the non-default case of PROFILER_UTILITY, the outer switch kicks in making it expand to PROFILE_START. PROFILE_END_FOR works analogously.
The EAT macro takes (msg) in both cases to nothing; otherwise, the original macro's called.
Is there a better way of achieving what I'm looking for?
Depends on what you're looking for. This approach shows what's possible with the C preprocessor.

I personally would go for something like
#include <stdio.h>
#define FOO_ENABLED 1
#define BAR_ENABLED 0
#define PROFILE_START(FLAG, msg) \
{ if (FLAG) printf("start(%s)\n", msg); }
int main()
{
PROFILE_START(FOO_ENABLED, "foo")
PROFILE_START(BAR_ENABLED, "bar")
return 0;
}
Any decent compiler would not generate any instructions for the if statement anyway.

Is such a helper macro possible?
No. As was covered in comments, you cannot generate macro definitions via macros.*
Is there a better way of achieving what I'm looking for?
Since the macro idea won't work,* any alternative that does work is better. Basically, you're looking for a code generator -- a program that will take as input a list of modules and produce as output C source (maybe a header) containing definitions of all the profiling macros for all the modules. You could write such a program in pretty much any language -- C, python, perl, shell script, whatever. Depending on your technology preferences and project context, you might even go with something like XSLT.
Each source file that wants to get the profiling macros then just #includes the generated header.
*In fact, you could use the C preprocessor, by performing a separate, standalone run on a different, for-purpose input file. But you cannot generate the macros in-place when you compile the source file(s) that wants to use them.

Related

Allowing a custom macro in #ifdef check

Imagine I have some "assert like" functionality, which declares a macro one way if a specific macro is defined, and a different way if it is not:
// in some header assert2.hpp
#ifdef NO_ASSERT2
#define assert2(x)
#else
#define assert2(x) assert2_handler(x);
#endif
Here, the NO_ASSERT2 macro is very much like the NDEBUG macro in standard assert(3).
What I'd like to do, however is allow the user to override the NO_ASSERT2 check with their own macro, before including the file. E.g., if you included assert2.hpp like this:
#define NO_ASSERT_KEY NO_ASSERT_CUSTOM
#include "assert2.hpp"
Then the macro NO_ASSERT_CUSTOM would be checked instead of the default NO_ASSERT2 for this translation unit.
It doesn't have to work exactly like the above - I just need some way to override the behavior on a per-file basis, without needing more than the 1 line of boilerplate shown above at the location of the include.
This isn't pretty... but this approach may work for you. It assumes that the macro is defined using either #define FOO, #define FOO 1, or -DFOO (assuming as typical that this creates something equivalent to #define FOO 1).
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B
#define GLUE3(A,B,C) GLUE3_I(A,B,C)
#define GLUE3_I(A,B,C) A##B##C
#define AGLUE3(A,B,C) AGLUE3_I(A,B,C)
#define AGLUE3_I(A,B,C) A##B##C
#define TEST_ASSERT_KEY GLUE3(NO_ASSERT_PROBE,0_,NO_ASSERT_KEY)
#define NO_ASSERT_PROBE0_NO_ASSERT_KEY AGLUE3(NO_ASSERT_PROBE,0_,NO_ASSERT2)
#define NO_ASSERT_PROBE0_ ,1
#define NO_ASSERT_PROBE0_1 ,1
#define NO_ASSERT_TEST SECOND(TEST_ASSERT_KEY,0)
With this, your usage would be:
#if NO_ASSERT_TEST
#define assert2(x)
#else
#define assert2(x) assert2_handler(x);
#endif
Here's a demo at stacked-crooked.
This uses pattern matching in the preprocessor via the indirect SECOND macro. The idea is that it expands to its second argument, but only indirectly... this allows you to construct as the first argument a pattern. Usually that first argument's ignored, but if you want to match something you can set it up to where the first argument would be a macro that expands with a comma; that shifts a new second argument in, replacing the default.
From here it's easier to explain backwards. NO_ASSERT_TEST uses TEST_ASSERT_KEY to construct a pattern with a default of 0. TEST_ASSERT_KEY builds NO_ASSERT_PROBE0_ concatenated with NO_ASSERT_KEY. When NO_ASSERT_KEY is defined, this would build NO_ASSERT_PROBE0_ concatenated with the expansion of what it's defined as. Otherwise it rebuilds the test token using NO_ASSERT_PROBE0_ concatenated with NO_ASSERT2.
Either way this is an indirect paste, so NO_ASSERT_KEY in the former case or NO_ASSERT2 in the latter is expanded first. In the former case, if say NO_ASSERT_KEY is NO_ASSERT_CUSTOM and NO_ASSERT_CUSTOM is not defined, this builds NO_ASSERT_PROBE0_NO_ASSERT_CUSTOM, which is just a normal identifier, which will be ignored, which results in 0 due to the SECOND in NO_ASSERT_TEST. But if NO_ASSERT_CUSTOM is defined per #define NO_ASSERT_CUSTOM, this produces NO_ASSERT_PROBE0_, which expands to ,1, which shifts 1 into the SECOND call in NO_ASSERT_TEST. Likewise if NO_ASSERT_CUSTOM is defined per -DNO_ASSERT_CUSTOM on the command line, that would (typically) make its definition equivalent to #define NO_ASSERT_CUSTOM 1, which would produce NO_ASSERT_PROBE0_1, which expands to ,1.
The cases for when NO_ASSERT_KEY is not defined are similar.
There's probably a prettier way to build this construct, if anyone wants to take a shot.

What does #define do if you only have an identifer

typically #define would be used to define a constant or a macro. However it is valid code to use #define in the following way.
#define MAX // does this do anything?
#define MAX 10 // I know how to treat this.
So, if I #define MAX 10, I know my pre-processor replaces all instances of MAX with 10. If someone uses #define MAX by itself however with no following replacement value, it's valid. Does this actually DO anything?
My reason for asking is that I am writing a compiler for c in c++ and handling preprocessor directives is required but I haven't been able to find out if there is any functionality I need to have when this occurs or if I just ignore this once my preprocess is done.
My first instinct is that this will create a symbol in my symbol table with no value named MAX, but it is equally possible it will do nothing.
As an add in question which is kind of bad form I know, but I'm really curious. Are there situations in real code where something like this would be used?
Thanks,
Binx
A typical example are header guards:
#ifndef MYHEADER
#define MYHEADER
...
#endif
You can test if something is defined with #ifdef / ifndef.
It creates a symbol with a blank definition, which can later be used in other preprocessor operations. There are a few things it can be used for:
1) Branching.
Consider the following:
#define ARBITRARY_SYMBOL
// ...
#ifdef ARBITRARY_SYMBOL
someCode();
#else /* ARBITRARY_SYMBOL */
someOtherCode();
#endif /* ARBITRARY_SYMBOL */
The existence of a symbol can be used to branch, selectively choosing the proper code for the situation. A good use of this is handling platform-specific equivalent code:
#if defined(_WIN32) || defined(_WIN64)
windowsCode();
#elif defined(__unix__)
unixCode();
#endif /* platform branching */
This can also be used to dummy code out, based on the situation. For example, if you want to have a function that only exists while debugging, you might have something like this:
#ifdef DEBUG
return_type function(parameter_list) {
function_body;
}
#endif /* DEBUG */
1A) Header guards.
Building on the above, header guards are a means of dummying out an entire header if it's already included in a project that spans multiple source files.
#ifndef HEADER_GUARD
#define HEADER_GUARD
// Header...
#endif /* HEADER_GUARD */
2) Dummying out a symbol.
You can also use defines with blank definitions to dummy out a symbol, when combined with branching. Consider the following:
#ifdef _WIN32
#define STDCALL __stdcall
#define CDECL __cdecl
// etc.
#elif defined(__unix__)
#define STDCALL
#define CDECL
#endif /* platform-specific */
// ...
void CDECL cdeclFunc(int, int, char, const std::string&, bool);
// Compiles as void __cdecl cdeclFunc(/* args */) on Windows.
// Compiles as void cdeclFunc(/* args */) on *nix.
Doing something like this allows you to write platform-independent code, but with the ability to specify the calling convention on Windows platforms. [Note that the header windef.h does this, defining CDECL, PASCAL, and WINAPI as blank symbols on platforms that don't support them.] This can also be used in other situations, whenever you need a preprocessor symbol to only expand to something else under certain conditions.
3) Documentation.
Blank macros can also be used to document code, since the preprocessor can strip them out. Microsoft is fond of this approach, using it in windef.h for the IN and OUT symbols often seen in Windows function prototypes.
There are likely other uses as well, but those are the only ones I can think of off the top of my head.
It doesn't "do" anything in the sense that it will not add anything to a line of code
#define MAX
int x = 1 + 2; MAX // here MAX does nothing
but what an empty define does is allow you to conditionally do certain things like
#ifdef DEBUG
// do thing
#endif
Similarly header guards use the existance of a macro to indicate if a file has already been included in a translation unit or not.
The C Preprocessor (CPP) creates a definitions table for all variables defined with the #define macro. As the CPP passes through the code, it does at least two things with this information.
First, it does a token replacement for the defined macro.
#define MAX(a,b) (a > b) ? (a) : (b)
MAX(1,2); // becomes (1 > 2) ? (1) : (2);
Second, it allows for those definitions to be searched for with other preprocessor macros such as #ifdef, #ifndef, #undef, or CPP extensions like #if defined(MACRO_NAME).
This allows for flexibility in using macro definitions in those cases when the value is not important, but the fact that a token is defined is important.
This allows for code like the following:
// DEBUG is never defined, so this code would
// get excluded when it reaches the compiler.
#ifdef DEBUG
// ... debug printing statements
#endif
#define does a character-for-character replacement. If you give no value, then the identifier is replaced by...nothing. Now this may seem strange. We often use this just to create an identifier whose existence can be checked with #ifdef or #ifndef. The most common use is in what are called "inclusion guards".
In your own preprocessor implementation, I see no reason to treat this as a special case. The behavior is the same as any other #define statement:
Add a symbol/value pair to the symbol table.
Whenever there is an occurrence of the symbol, replace it with its value.
Most likely, step 2 will never occur for a symbol with no value. However, if it does, the symbol is simply removed since its value is empty.

Preprocessor macro without replacement C++

According to cplusplus.com, the syntax to define a macro is:
#define identifier replacement
However, I sometimes stumble upon a macro definition which doesn't contain a replacement. For example in afxwin.h, there is the following preprocessor definition:
#define afx_msg // intentional placeholder
My questions:
What happens at compile-time when a preprocessor definition that doesn't have a replacement is used? Is it simply ignored? For example, does the line afx_msg void OnAddButton(); become void OnAddButton();?
What is the purpose of using preprocessor without replacement? Is it simply to make code more clear?
"Nothing" (no text) is a valid replacement text for a macro. It will simply be removed (more precisely, replaced by nothing) by the preprocessor.
There are multiple reasons why you'd use something like this. One is to simply use the macro in #ifdef and similar constructrs.
Another is conditional compilation. A typical use case is public APIs and DLL exports. On Windows, you need to mark a function as exported from a DLL (when building the DLL) or as imported from a DLL (when linking against the DLL). On ELF systems, no such declarations are necessary. Therefore, you'll often see code like this in public library headers:
#ifdef _WIN32
#ifdef BUILDING_MYLIB
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
void MYLIB_API myApiFunction();
Yet another reason could be code processing tools. Perhaps you have a tool which parses source code, extracting a list of functions with a certain marker. You can define such a marker as an empty macro.
#define bla
simply defines bla.
you can use it with
#ifdef bla
...
place some code here
...
#endif
a typical use case is #define DEBUG to enable special code parts in debugging mode.
Another way to set such things from "outside" is:
g++ -DDEBUG x.cpp
which also sets the macro DEBUG defined.
And every header file should have something like:
#ifndef THIS_HEADER_INCLUDE_GUARD
#define THIS_HEADER_INCLUDE_GUARD
...
rest of header file
...
#endif
This simply protects your header file for (recursivly) read more the once.
Some can be done with implementation specific #pragma once.
the preprocessor processes it, removing it and replacing it with nothing
could be a variety of reasons, including readability, portability, custom compiler features, etc.

Preprocessor macros: how to insert arguments?

The code has a number of following sections:
int filter;
#ifdef INPUTFILTER_FOO
LOG4CXX_DEBUG(log, "FOO filter used");
filter = F_FOO;
#endif
They are used multiple times in the code (used to provide I/O, threading support etc for all testing configurations), Circa they are essential for debugging but make the code look harsh, want to replace them with macros, one for each category_type namespace.
So, want to expand the following:
MACROSTUFFBAZ(log2, stuff, "BAZ") <- the text part is unique for each class, so it needs to be included in macro too.
to:
#ifdef INPUTSTUFF_BAZ
LOG4CXX_DEBUG(log2, "BAZ stuff used");
stuff = S_BAZ;
#endif
To define macros, plan to use this:
debug.hpp:
#ifdef INPUTSTUFF_BAZ
#define MACROSTUFFBAZ ...
#else
#define MACROSTUFFBAZ
.. no code!
#endif
#endif
(at least this will give a clear overview of the things currently undergoing probation, without seeing them around the code)
Here's my try, although i'm not 100% sure if it works cause i'm unable to test it right now, and also different compilers handle preprocessor macros a little bit differently. But I think something like this works at least in visual studio.
Basically, you have to use a helper macro to convert the parameter into a string. And secondly, you can use ## to concatenate identifiers:
#define PRMTOSTR_HLPR(x) #x
#define PRMTOSTR(x) PRMTOSTR_HLPR(x)
#ifdef INPUTSTUFF_BAZ
#define MACROSTUFFBAZ(A,B,C) \
LOG4CXX_DEBUG(A, PRMTOSTR(C)" stuff used"); \
B = S_##C;
#else
#define MACROSTUFFBAZ(A,B,C)
#endif
//used like this:
MACROSTUFFBAZ(log2, stuff, BAZ)
edit: The helper macro is actually not needed here, so you can just put #C directly in the definition of MACROSTUFFBAZ.

What is the purpose of the #define directive in C++?

What is the role of the #define directive?
#define is used to create macros in C and in C++. You can read more about it in the C preprocessor documentation. The quick answer is that it does a few things:
Simple Macros - basically just text replacement. Compile time constants are a good example:
#define SOME_CONSTANT 12
simply replaces the text SOME_CONSTANT with 12 wherever it appears in your code. This sort of macro is often used to provide conditional compilation of code blocks. For example, there might be a header included by each source file in a project with a list of options for the project:
#define OPTION_1
#define OPTION_2
#undef OPTION_3
And then code blocks in the project would be wrapped with matching #ifdef/#endif# blocks to enable and disable those options in the finished project. Using the -D gcc flag would provide similar behaviour. There are strong opinions as to whether or not this method is really a good way to provide configuration for an application, however.
Macros with arguments - allows you to make 'function-like' macros that can take arguments and manipulate them. For example:
#define SQUARE(x) ((x) * (x))
would return the square of the argument as its result; be careful about potential order-of-operations or side-effect problems! The following example:
int x = SQUARE(3); // becomes int x = ((3) * (3));
will works fine, but something like:
int y = SQUARE(f()); // becomes int y = ((f()) * (f()));
will call f() twice, or even worse:
int z = SQUARE(x++); // becomes int z = ((x++) * (x++));
results in undefined behaviour!
With some tools, macros with arguments can also be variadic, which can come in handy.
As mentioned below in the comments, overuse of macros, or the development of overly complicated or confusing macros is considered bad style by many - as always, put the readability, maintainability, and debuggability of your code above 'clever' technical tricks.
#define (and it's opposite, #undef) can be used to set compiler directives which can then be tested against using #ifndef or #ifdef. This allows for custom behaviors to be defined within the source file. It's used commonly to compile for different environments or debug code.
An example:
#define DEBUG
#ifdef DEBUG
//perform debug code
#endif
The most common use (by far) of #define is for include guards:
// header.hh
#ifndef HEADER_HH_
#define HEADER_HH_
namespace pony {
// ...
}
#endif
Another common use of #define is in creating a configuration file, commonly a config.h file, where we #define macros based on various states and conditions. Then, in our code we test these macros with #ifdef, #elif defined() etc. to support different compiles for different situations. This is not as solid as the include-guard idiom and you need to be careful here because if the branching is wrong then you can get very obscure compiler errors, or worse, runtime behavior.
In general, other than for include guards you need to think through (twice, preferably) about the problem, and see if you can use the compiler rather than the preprocessor to solve it. The compiler is just smarter than the preprocessor. Not only that, but the compiler can't possibly confuse the preprocessor, whereas the preprocessor most definitely can confuse and mislead the compiler.
The #define directive has two common uses.
The first one, is control how the compiler will act. To do this, we also need #undef, #ifdef and #ifndef. (and #endif too...)
You can make "compiler logic" this way. A common use is to activate or not a debug portion of the code, like that:
#ifdef DEBUG
//debug code here
#endif
And you would be able to for example compile the debug code, by writing a #define DEBUG
Another use of this logic stuff, is to avoid double includes...
Example, file A, #includes file B and C. But file B also includes C. This likely will result in a compilation error, because "C" exists twice.
The solution is write:
#ifndef C_FILE_INCLUDED
#define C_FILE_INCLUDED
//the contents of header "c" go here.
#endif
The other use of #define, is make macros.
The most simple ones, consist of simple substitutions, like:
#define PI 3.14159265
float perimeter(float radius) {
return radius*2*PI;
}
or
#define SHOW_ERROR_MESSAGE printf("An serious error happened");
if ( 1 != 1 ) { SHOW_ERROR_MESSAGE }
Then you can also make macros that accept arguments, printf itself usually is a macro, created with a #define in a header file.
But this should not be done, for two reaons:
first, the speed os macros, is the same of using inline, and second, we have c++ templates, that allow more control over functions with variable type. So, the only reason to use macros with arguments, is make strange constructs, that will be hard to understand later, like metaprogrammed stuff...
In C++, #define has very narrow, specialized roles:
Header guards, described in other answers
Interacting with the standard libraries. For instance, #defining WINDOWS_LEAN_AND_MEAN before including windows.h turns off certain often-problematic macros like MAX.
Advanced macros involving stringization (ie, macros that print debugging messages) or token-pasting.
You should avoid using #define for the following purposes. The reasons are many; see for instace this FAQ entry.
Compile-time constants. Use const instead.
Simple macro functions. Use inline functions and templates instead.
in C or C++ #define allows you to create preprocessor Macros.
In the normal C or C++ build process the first thing that happens is that the PreProcessor runs, the preprocessor looks though the source files for preprocessor directives like #define or #include and then performs simple operations with them.
in the case of a #define directive the preprocessor does simple text based substitution.
For example if you had the code
#define PI 3.14159f
float circum = diameter*PI;
the preprocessor would turn it into:
float circum = diameter* 3.14159;
by simply replacing the instances of PI with the corresponding text. This is only the simplest form of a #define statement for more advanced uses check out this article from MSDN
inCorrectUseOfHashDefine()
{
The role of #define is to baffle people who inherit your code with out of the blue statements like:
foreverandever
because of:
#define foreverandever for(;;)
}
Please favour constants over #define.
It also for setting compiler directives...
Most things about #defines have been already told, but it's not clear that C++ has better replacements for most of their uses:
#define to define numerical constants can be easily replaced by a const "variable", that, as a #define, doesn't really exist in the compiled executable. AFAIK it can be used in almost all the situations where you could use a #defined numerical constant, including array bounds. The main advantage for me is that such constants are clearly typed, so there's no need to add casts in the macros "just to be sure", and are scoped, so they can be kept in namespaces/classes/functions, without polluting all the application.
const int max_array_size=50;
int an_array[max_array_size];
#define to create macros: macros can often be replaced by templates; for example, the dreaded MAX macro
#define MAX(a,b) ((a)<(b)?(b):(a))
, which has several downsides (e.g. repeated arguments evaluation, inevitable inline expansion), can be replaced by the max function
template<typename T> T & max(T & a, T & b)
{
return a<b?b:a;
}
which can be type-safe (in this version the two arguments are forced to be of the same type), can be expanded inline as well as not (it's compiler decision), evaluates the arguments just once (when it's called), and is scoped. A more detailed explanation can be found here.
Still, macros must still be used for include guards, to create some kind of strange language extensions that expand to more line of code, that have unbalanced parenthesis, etc.