In C, the macro is used to define any constant value or any variable with its value in the entire program that will be replaced by this macro name, where macro contains the set of code that will be called when the macro name is used in the program.
The Concept of C Macros Macros are generally used to define constant values that are being used repeatedly in program. Macros can even accept arguments and such macros are known as function-like macros. It can be useful if tokens are concatenated into code to simplify some complex declarations.
A quick google for "Why should I avoid macros in C++" brought up this: securecoding.cert.org/confluence/display/cplusplus/… Well, you should avoid using a macro where some other feature provides a better alternative; otherwise use a macro.
As wrappers for debug functions, to automatically pass things like __FILE__
, __LINE__
, etc:
#ifdef ( DEBUG )
#define M_DebugLog( msg ) std::cout << __FILE__ << ":" << __LINE__ << ": " << msg
#else
#define M_DebugLog( msg )
#endif
Methods must always be complete, compilable code; macros may be code fragments. Thus you can define a foreach macro:
#define foreach(list, index) for(index = 0; index < list.size(); index++)
And use it as thus:
foreach(cookies, i)
printf("Cookie: %s", cookies[i]);
Since C++11, this is superseded by the range-based for loop.
Header file guards necessitate macros.
Are there any other areas that necessitate macros? Not many (if any).
Are there any other situations that benefit from macros? YES!!!
One place I use macros is with very repetitive code. For example, when wrapping C++ code to be used with other interfaces (.NET, COM, Python, etc...), I need to catch different types of exceptions. Here's how I do that:
#define HANDLE_EXCEPTIONS \
catch (::mylib::exception& e) { \
throw gcnew MyDotNetLib::Exception(e); \
} \
catch (::std::exception& e) { \
throw gcnew MyDotNetLib::Exception(e, __LINE__, __FILE__); \
} \
catch (...) { \
throw gcnew MyDotNetLib::UnknownException(__LINE__, __FILE__); \
}
I have to put these catches in every wrapper function. Rather than type out the full catch blocks each time, I just type:
void Foo()
{
try {
::mylib::Foo()
}
HANDLE_EXCEPTIONS
}
This also makes maintenance easier. If I ever have to add a new exception type, there's only one place I need to add it.
There are other useful examples too: many of which include the __FILE__
and __LINE__
preprocessor macros.
Anyway, macros are very useful when used correctly. Macros are not evil -- their misuse is evil.
Mostly:
__LINE__
and __FILE__
)If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With