Differencebetween a MACro and a Const in C++

What is the difference between a macro and a const in C++?

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);
}

What is the difference between macro constants and constant variables in C?

Macros are handled by the pre-processor - the pre-processor does text replacement in your source file, replacing all occurances of 'A' with the literal 8.

Constants are handled by the compiler. They have the added benefit of type safety.

For the actual compiled code, with any modern compiler, there should be zero performance difference between the two.

What is the difference between #define and const?

The #define directive is a preprocessor directive; the preprocessor replaces those macros by their body before the compiler even sees it. Think of it as an automatic search and replace of your source code.

A const variable declaration declares an actual variable in the language, which you can use... well, like a real variable: take its address, pass it around, use it, cast/convert it, etc.

Oh, performance: Perhaps you're thinking that avoiding the declaration of a variable saves time and space, but with any sensible compiler optimisation levels there will be no difference, as constant values are already substituted and folded at compile time. But you gain the huge advantage of type checking and making your code known to the debugger, so there's really no reason not to use const variables.

C/C++ macros instead of const

Reason #1: Scoping. Macros totally ignore scope.

namespace SomeNS {

enum Functor {
MIN = 0
, AVG = 1
, MAX = 2
};

}

If the above code happens to be included in a file after the definition of the MAX macro, it will happily get preprocessed into 80 = 2, and fail compiling spectacularly.

Additionally, const variables are type safe, can be safely initialised with constant expressions (without need for parentheses) etc.

Also note that when the compiler has access to the const variable's definition when using it, it's allowed to "inline" its value. So if you never take its address, it does no even need not take up space.

Using macro definition vs const variable

Does the first version increase the binary size (comparing the first second)?

No. Since the string is used only once, it will appear only once in the compiled file.

Does the second version consume more memory (comparing the first one)?

No. It works with memory in pretty much the same manner.

What are the performance impacts of both implementations? Which should run faster and why?

Both implementations copy the string around: the method receives newValue by value, copying it. This copying will dominate the performance, I guess.

However, as always with performance, just measure it - it should be easy, since you already have both versions of the code implemented.

Which is preferable/beneficial in which condition?

Macros are not an idiomatic solution in C++. Use the const string.

Is there any better way for implementation of setting the default value?

Receive the new string by reference. Other than that, not so much. I assume here the default is a short string, like "none" or "default". These strings have short string optimization, so it doesn't matter much how you store it.

As always with performance, if you see that your method is a performance bottleneck, optimize it. If you don't know, don't optimize it.

What makes a better constant in C, a macro or an enum?

In terms of readability, enumerations make better constants than macros, because related values are grouped together. In addition, enum defines a new type, so the readers of your program would have easier time figuring out what can be passed to the corresponding parameter.

Compare

#define UNKNOWN  0
#define SUNDAY 1
#define MONDAY 2
#define TUESDAY 3
...
#define SATURDAY 7

to

typedef enum {
UNKNOWN,
SUNDAY,
MONDAY,
TUESDAY,
...
SATURDAY,
} Weekday;

It is much easier to read code like this

void calendar_set_weekday(Weekday wd);

than this

void calendar_set_weekday(int wd);

because you know which constants it is OK to pass.

static const vs #define vs enum

It depends on what you need the value for. You (and everyone else so far) omitted the third alternative:

  1. static const int var = 5;
  2. #define var 5
  3. enum { var = 5 };

Ignoring issues about the choice of name, then:

  • If you need to pass a pointer around, you must use (1).
  • Since (2) is apparently an option, you don't need to pass pointers around.
  • Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
  • (1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
  • (1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
  • Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
  • (1) cannot be used in places like switch statements; both (2) and (3) can.
  • (1) cannot be used to initialize static variables; both (2) and (3) can.
  • (2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
  • You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.

So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors — and you have to think harder if you need to satisfy both at once.

If you were asking about C++, then you'd use option (1) — the static const — every time.

In C++, is it better to use #define or const to avoid magic numbers?

Don't worry about efficiency in this case since all of them will be computed in compile-time.

You should stop using Macros (at least to define constants) whenever you can. Macros are wild things against namespaces and scopes. On the other hand const objects have type and this can reduce unintended mistakes.

It's always useful to read Stroustrup's piece of advises: "So, what's wrong with using macros?"



Related Topics



Leave a reply



Submit