I was asked this question in a technical interview:
What is the difference between a
const
and a macro in C++?
My answer was that a macro is a preprocessor directive and it could be difficult to debug the application if you use a macro since it is replaced with the constant expression before compilation, whereas a const
can have a type identifier and is easy to debug.
Could anyone point out any other difference and which should be preferred?
EDIT:
From the IBM documentation for C++:
The following are some differences between
#define
and theconst
type qualifier:
The
#define
directive can be used to create a name for a numerical, character, or string constant, whereas a const object of any type can be declared.A const object is subject to the scoping rules for variables, whereas a constant created using
#define
is not. Unlike aconst
object, the value of a macro does not appear in the intermediate source code used by the compiler because they are expanded inline. The inline expansion makes the macro value unavailable to the debugger.A macro can be used in a constant expression, such as an array bound, whereas a
const
object cannot. (I think we surely need to use macro to definearray_size
.The compiler does not type-check a macro, including macro arguments.
#define is a preprocessor directive. Constants are used to make variables constant such that never change during execution once defined.
The difference is that #define is processed by the preprocessor doing what amounts to simple text replacement. Const values defined like this are not visible for the actual compiler, while a variable defined with the const modifier is an actual typed "variable" (well not really that variable).
Const (constant) in programming is a keyword that defines a variable or pointer as unchangeable. A const may be applied in an object declaration to indicate that the object, unlike a standard variable, does not change. Such fixed values for objects are often termed literals.
In the C Programming Language, the #define directive allows the definition of macros within your source code. These macro definitions allow constant values to be declared for use throughout your code. Macro definitions are not variables and cannot be changed by your program code like variables.
Macros and constants are not remotely the same thing, each is sometimes appropriate for the circumstances, and your answer only scratches at the surface of the difference. Also, C++ has two different kinds of constants.
A constant defined with the const
qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address. (The compiler might optimize away some of these properties if it can get away with it: for instance, constants whose address is never used may not get emitted into the executable image. But this is only by the grace of the as-if rule.) The only thing you can't do to a const
datum is change its value. A constant defined with enum
is a little different. It has a type and a size, but it doesn't have linkage, you can't take its address, and its type is unique. Both of these are processed during translation phase 7, so they can't be anything but an lvalue or rvalue. (I'm sorry about the jargon in the preceding sentence, but I would have to write several paragraphs otherwise.)
A macro has far fewer constraints: it can expand to any sequence of tokens, as long as the overall program remains a well-formed program. It doesn't have any of the properties of a variable. Applying sizeof
or &
to a macro may or may not do something useful, depending on what the macro expands to. Macros are sometimes defined to expand to numeric literals, and such macros are sometimes thought of as constants, but they're not: "the compiler proper" (that is, translation phase 7) sees them as numeric literals.
It is generally considered good practice, nowadays, not to use a macro when a constant will do. Macros don't obey the same scoping rules as all other identifiers, which can be confusing, and if you use a constant you give more information to translation phase 7 and thus also to the debugger. However, macros permit you to do things that cannot be done any other way, and if you need to do one of those things, you should not hesitate to use them. (Macros that are pulling their weight, in this sense, generally do not just expand to numeric literals, though I am not going to say never.)
EDIT: Here's an example of a macro doing something interesting. It is in no way, shape or form a constant. There may well be a way to get the same effect without a macro (if you know one that doesn't involve stringstreams, I'd be curious to hear about it!) but I think it makes a good illustration of both the power and the danger of macros (for the latter, consider what it would do if it was used outside of one very specific context...)
static double elapsed() { ... } #define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] " // usage: for (vector<string>::iterator f = files.begin(); f != files.end(); f++) { cout << ELAPSED << "reading file: " << *f << '\n'; process_file(*f); }
One should prefer const int sum = 1;
over #define sum 1
for a number of reasons:
Scope Based Mechanism:
#define
s don't respect scopes so there is no way to create a class scoped namespace. While const variables can be scoped in classes.
Avoiding Weird magical numbers during compilation errors:
If you are using #define
those are replaced by the pre-processor at time of precompilation So if you receive an error during compilation, it will be confusing because the error message wont refer the macro name but the value and it will appear a sudden value, and one would waste lot of time tracking it down in code.
Ease of Debugging:
Also for same reasons, while debugging #define
would provide no help really.
To avoid both above situations const
will be a better choice.
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