A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. There are two kinds of macros. They differ mostly in what they look like when they are used. Object-like macros resemble data objects when used, function-like macros resemble function calls. This solves example 1, because the macro is in one statement block. But example 2 is broken because we put a semicolon after the call to the macro. This makes the compiler think the semicolon is a statement by itself, which means the else statement doesn't correspond to any if statement! When the macro is expanded, each use of a parameter in its body is replaced by the tokens of the corresponding argument. (You need not use all of the parameters in the macro body.) As an example, here is a macro that computes the minimum of two numeric values, as it is defined in many C.
Active2 months ago
I always saw examples and cases where using a macro is better than using function.
Could someone explain me with an example the disadvantage of a macro compared to a function?
A-Sharabiani
7,45310 gold badges61 silver badges90 bronze badges
KyrolKyrol
1,4456 gold badges24 silver badges37 bronze badges
11 Answers
Macros are error-prone because they rely on textual substitution and do not perform type-checking. For example, this macro:
works fine when used with an integer:
but does very strange things when used with expressions:
Putting parentheses around arguments helps but doesn't completely eliminate these problems.
When macros contain multiple statements, you can get in trouble with control-flow constructs:
The usual strategy for fixing this is to put the statements inside a 'do { .. } while (0)' loop.
If you have two structures that happen to contain a field with the same name but different semantics, the same macro might work on both, with strange results:
Finally, macros can be difficult to debug, producing weird syntax errors or runtime errors that you have to expand to understand (e.g. with gcc -E), because debuggers cannot step through macros, as in this example:
Inline functions and constants help to avoid many of these problems with macros, but aren't always applicable. Where macros are deliberately used to specify polymorphic behavior, unintentional polymorphism may be difficult to avoid. C++ has a number of features such as templates to help create complex polymorphic constructs in a typesafe way without the use of macros; see Stroustrup's The C++ Programming Language for details.
AustinWBryan
2,4162 gold badges15 silver badges32 bronze badges
D CoetzeeD Coetzee
3,5001 gold badge19 silver badges18 bronze badges
Macro features:
- Macro is Preprocessed
- No Type Checking
- Code Length Increases
- Use of macro can lead to side effect
- Speed of Execution is Faster
- Before Compilation macro name is replaced by macro value
- Useful where small code appears many time
- Macro does not Check Compile Errors
Function features:
- Function is Compiled
- Type Checking is Done
- Code Length remains Same
- No side Effect
- Speed of Execution is Slower
- During function call, Transfer of Control takes place
- Useful where large code appears many time
- Function Checks Compile Errors
25.7k7 gold badges100 silver badges123 bronze badges
Side-effects are a big one. Here's a typical case:
gets expanded to:
x
gets incremented twice in the same statement. (and undefined behavior)
Writing multi-line macros are also a pain:
They require a
at the end of each line.
Macros can't 'return' anything unless you make it a single expression:
Can't do that in a macro unless you use GCC's expression statement. (EDIT: You can use a comma operator though.. overlooked that.. But it might still be less readable.)
Order of Operations: (courtesy of @ouah)
gets expanded to:
But
AustinWBryan
&
has lower precedence than <
. So 0xFF < 42
gets evaluated first.
2,4162 gold badges15 silver badges32 bronze badges
MysticialMysticial
400k40 gold badges305 silver badges312 bronze badges
Flexo♦Flexo
72.7k22 gold badges159 silver badges238 bronze badges
No type checking of parameters and code is repeated which can lead to code bloat. The macro syntax can also lead to any number of weird edge cases where semi-colons or order of precedence can get in the way. Here's a link that demonstrates some macro evil
Michael DorganMichael Dorgan
11k2 gold badges24 silver badges57 bronze badges
When in doubt, use functions (or inline functions).
However answers here mostly explain the problems with macros, instead of having some simple view that macros are evil because silly accidents are possible.
You can be aware of the pitfalls and learn to avoid them. Then use macros only when there is a good reason to.
You can be aware of the pitfalls and learn to avoid them. Then use macros only when there is a good reason to.
There are certain exceptional cases where there are advantages to using macros, these include:
- Generic functions, as noted below, you can have a macro that can be used on different types of input arguments.
- Variable number of arguments can map to different functions instead of using C's
va_args
.
eg: https://stackoverflow.com/a/24837037/432509. - They can optionally include local info, such as debug strings:
(__FILE__
,__LINE__
,__func__
). check for pre/post conditions,assert
on failure, or even static-asserts so the code won't compile on improper use (mostly useful for debug builds). - Inspect input args, You can do tests on input args such as checking their type, sizeof, check
struct
members are present before casting
(can be useful for polymorphic types).
Or check an array meets some length condition.
see: https://stackoverflow.com/a/29926435/432509 - While its noted that functions do type checking, C will coerce values too (ints/floats for example). In rare cases this may be problematic. Its possible to write macros which are more exacting then a function about their input args. see: https://stackoverflow.com/a/25988779/432509
- Their use as wrappers to functions, in some cases you may want to avoid repeating yourself, eg..
func(FOO, 'FOO');
, you could define a macro that expands the string for youfunc_wrapper(FOO);
- When you want to manipulate variables in the callers local scope, passing pointer to a pointer works just fine normally, but in some cases its less trouble to use a macro still.
(assignments to multiple variables, for a per-pixel operations, is an example you might prefer a macro over a function.. though it still depends a lot on the context, sinceinline
functions may be an option).
Admittedly, some of these rely on compiler extensions which aren't standard C. Meaning you may end up with less portable code, or have to
ifdef
them in, so they're only taken advantage of when the compiler supports.
Noting this since its one of the most common causes of errors in macros (passing in
x++
for example, where a macro may increment multiple times).
Samsung dvd r120 manual pdf. its possible to write macros that avoid side-effects with multiple instantiation of arguments.
C11 Generic
If you like to have
square
macro that works with various types and have C11 support, you could do this..
Statement expressions
This is a compiler extension supported by GCC, Clang, EKOPath & Intel C++ (but not MSVC);
Each call to the mailslot write function results in a two byte return value being written into the response packet. The default target for this exploit should succeed on Windows NT 4.0, Windows 2000 SP0-SP4+, Windows XP SP0-SP1 and Windows 2003 SP0.Module type: exploitRank: goodPlatforms: WindowsThis module triggers a kernel pool corruption bug in SRV.SYS. The code which creates this packet fails to consider these two bytes in the allocation routine, resulting in a slow corruption of the kernel memory pool. Metasploit windows xp sp3 exploits free. These two bytes are almost always set to 'xffxff' (a short integer with value of -1).Module type: auxiliaryRank: normalThis module exploits a NULL pointer dereference flaw in the SRV.SYS driver of the Windows operating system. A failed exploit attempt will likely result in a complete reboot on Windows 2000 and the termination of all SMB-related services on Windows XP.
So the disadvantage with macros is you need to know to use these to begin with, and that they aren't supported as widely.
One benefit is, in this case, you can use the same
square
function for many different types.
Community♦
ideasman42ideasman42
14.6k9 gold badges84 silver badges160 bronze badges
one drawback to macros is that debuggers read source code, which does not have expanded macros, so running a debugger in a macro is not necessarily useful. Needless to say, you cannot set a breakpoint inside a macro like you can with functions.
jim mcnamarajim mcnamara
14k2 gold badges24 silver badges43 bronze badges
Adding to this answer.
Macros are substituted directly into the program by the preprocessor (since they basically are preprocessor directives). So they inevitably use more memory space than a respective function. On the other hand, a function requires more time to be called and to return results, and this overhead can be avoided by using macros.
Also macros have some special tools than can help with program portability on different platforms.
Macros don't need to be assigned a data type for their arguments in contrast with functions.
Overall they are a useful tool in programming. And both macroinstructions and functions can be used depending on the circumstances.
NikosNikos
1,7284 gold badges22 silver badges37 bronze badges
Functions do type checking. This gives you an extra layer of safety.
ncmathsadistncmathsadist
2,9523 gold badges22 silver badges35 bronze badges
I did not notice, in the answers above, one advantage of functions over macros that I think is very important:
Functions can be passed as arguments, macros cannot.
Concrete example: You want to write an alternate version of the standard 'strpbrk' function that will accept, rather than an explicit list of characters to search for within another string, a (pointer to a) function that will return 0 until a character is found that passes some test (user-defined). One reason you might want to do this is so that you can exploit other standard library functions: instead of providing an explicit string full of punctuation, you could pass ctype.h's 'ispunct' instead, etc. If 'ispunct' was implemented only as a macro, this wouldn't work.
There are lots of other examples. For example, if your comparison is accomplished by macro rather than function, you can't pass it to stdlib.h's 'qsort'.
C Macro Example Code
An analogous situation in Python is 'print' in version 2 vs. version 3 (non-passable statement vs. passable function).
Sean RostamiSean Rostami
If you pass function as an argument to macro it will be evaluated every time.For example, if you call one of the most popular macro:
like that
functionThatTakeLongTime will be evaluated 5 times which can significantly drop perfomance
SafferSaffer
Not the answer you're looking for? Browse other questions tagged cfunctionc-preprocessor or ask your own question.
- C++ Basics
- C++ Object Oriented
- C++ Advanced
- C++ Useful Resources
- Selected Reading
The preprocessors are the directives, which give instructions to the compiler to preprocess the information before actual compilation starts.
All preprocessor directives begin with #, and only white-space characters may appear before a preprocessor directive on a line. Preprocessor directives are not C++ statements, so they do not end in a semicolon (;).
You already have seen a #include directive in all the examples. This macro is used to include a header file into the source file.
There are number of preprocessor directives supported by C++ like #include, #define, #if, #else, #line, etc. Let us see important directives −
The #define Preprocessor
The #define preprocessor directive creates symbolic constants. The symbolic constant is called a macro and the general form of the directive is −
When this line appears in a file, all subsequent occurrences of macro in that file will be replaced by replacement-text before the program is compiled. For example −
Now, let us do the preprocessing of this code to see the result assuming we have the source code file. So let us compile it with -E option and redirect the result to test.p. Now, if you check test.p, it will have lots of information and at the bottom, you will find the value replaced as follows −
Function-Like Macros
You can use #define to define a macro which will take argument as follows −
If we compile and run above code, this would produce the following result −
Conditional Compilation
There are several directives, which can be used to compile selective portions of your program's source code. This process is called conditional compilation.
The conditional preprocessor construct is much like the ‘if’ selection structure. Consider the following preprocessor code −
You can compile a program for debugging purpose. You can also turn on or off the debugging using a single macro as follows −
This causes the cerr statement to be compiled in the program if the symbolic constant DEBUG has been defined before directive #ifdef DEBUG. You can use #if 0 statment to comment out a portion of the program as follows −
Let us try the following example −
If we compile and run above code, this would produce the following result −
The # and ## Operators
The # and ## preprocessor operators are available in C++ and ANSI/ISO C. The # operator causes a replacement-text token to be converted to a string surrounded by quotes.
Consider the following macro definition −
If we compile and run above code, this would produce the following result −
Let us see how it worked. It is simple to understand that the C++ preprocessor turns the line −
Above line will be turned into the following line −
The ## operator is used to concatenate two tokens. Here is an example −
When CONCAT appears in the program, its arguments are concatenated and used to replace the macro. For example, CONCAT(HELLO, C++) is replaced by 'HELLO C++' in the program as follows.
If we compile and run above code, this would produce the following result −
Let us see how it worked. It is simple to understand that the C++ preprocessor transforms −
Above line will be transformed into the following line −
Predefined C++ Macros
C++ provides a number of predefined macros mentioned below −
Sr.No | Macro & Description |
---|---|
1 |
__LINE__
This contains the current line number of the program when it is being compiled.
|
2 |
__FILE__
This contains the current file name of the program when it is being compiled.
|
3 |
__DATE__
This contains a string of the form month/day/year that is the date of the translation of the source file into object code.
|
4 |
__TIME__
This contains a string of the form hour:minute:second that is the time at which the program was compiled.
|
Let us see an example for all the above macros −
If we compile and run above code, this would produce the following result −