I have seen a lot of programs using #define
at the beginning. Why shouldn't I declare a constant global variable instead ?

- 52,653
- 6
- 59
- 97

- 2,727
- 1
- 18
- 29
-
2Using #define is not a best practice. – upaang saxena Jun 02 '15 at 13:07
-
1@upaangsaxena really? why? – Iharob Al Asimi Jun 02 '15 at 13:08
-
1You should really decide if you want to know it for C or C++. With this respect they are really quite different. For C you have https://stackoverflow.com/questions/1674032/static-const-vs-define-in-c. And please, people, look at the tags of a question and be precise for which one you answer. – Jens Gustedt Jun 02 '15 at 13:15
-
@iharob- Because, using #define can give us some unwanted errors at run-time for larger applicaitons, because its a preprocessor and changes names of the variable to the value defined. It may lead to some errors. So, its not a best practice. – upaang saxena Jun 02 '15 at 13:21
-
@LightnessRacesinOrbit, it is very different in C. In C, `const` qualified variables can't e.g used as static array dimension and similar things. So for integer constants that you want to use for that, you *have* to use macros or enumeration constants. And for any header code that is to be included by both languages, you have to do the same. – Jens Gustedt Jun 02 '15 at 13:26
-
@Jens: _"In C, `const` qualified variables can't e.g used as static array dimension and similar things."_ Yikes! :( – Lightness Races in Orbit Jun 02 '15 at 13:27
-
@upaangsaxena. #define SETBITS(s,bv,m) (((s) & ~(m)) | ((bv) & (m))) ... A macro like this has good chance of very goog optimization ... !!! – Sir Jo Black Jun 02 '15 at 13:27
-
@SergioFormiggini: Literally no more so than a function whose definition is visible in all translation units in which is it called. It's 2015, not 1972. – Lightness Races in Orbit Jun 02 '15 at 13:28
-
@Sourav: C or C++? Pick _one_. – Lightness Races in Orbit Jun 02 '15 at 13:30
-
@LightnessRacesinOrbit, do you think this is funny? – Jens Gustedt Jun 02 '15 at 13:30
-
@Lightness Races in Orbit (Tpol) ... Think to use an MCU or a compiler that doesn't have good optimization. You (modern programmer) thinks the compiler is God ... :) – Sir Jo Black Jun 02 '15 at 13:31
-
Ops, I didn't read the question was about constant ... :) – Sir Jo Black Jun 02 '15 at 13:33
-
@SergioFormiggini: The compiler _is_ God, and has been for several decades. – Lightness Races in Orbit Jun 02 '15 at 13:35
-
@Jens: Do I think _what_ is funny? – Lightness Races in Orbit Jun 02 '15 at 13:36
-
@LightnessRacesinOrbit, citing a phrase from a comment of mine and just adding "Yikes! :(" – Jens Gustedt Jun 02 '15 at 13:37
-
@LightnessRacesinOrbit. The compiler is "God" because the thoughts of men who don't think the compiler is God. – Sir Jo Black Jun 02 '15 at 13:43
-
@JensGustedt: Ehm no, it's not funny. It's a shocking and sad-to-hear fact about C, that I was glad you informed me about. Will you get off my back, please? – Lightness Races in Orbit Jun 02 '15 at 13:44
3 Answers
(This is a C++ answer. In C, there is a major advantage to using macros, which is that they are pretty much the only way you can get a true constant-expression.)
What is the benefit of using
#define
to declare a constant?
There isn't one.
I have seen a lot of programs using
#define
at the beginning.
Yes, there is a lot of bad code out there. Some of it is legacy, and some of it is due to incompetence.
Why shouldn't I declare a constant global variable instead ?
You should.
A const
object is not only immutable, but has a type and is far easier to debug, track and diagnose, since it actually exists at compilation time (and, crucially, has a name in a debug build).
Furthermore, if you abide by the one-definition rule, you don't have to worry about causing an almighty palaver when you change the definition of a macro and forget to re-compile literally your entire project, and any code that is a dependent of that project.
And, yes, it's ironic that const
objects are still called "variables"; of course, in practice, they are not variable in the slightest.

- 378,754
- 76
- 643
- 1,055
-
1Yup, this. You should use `const` in preference to `#define` every time it is capable of being a replacement. I would note, however, that `const` variables technically are not globals but module-scoped. – Jack Aidley Jun 02 '15 at 13:12
-
@JackAidley: That's not true, though [it _is_ true that _by default_ a `const` object declared at namespace scope has internal linkage](http://stackoverflow.com/a/998457/560648). But you can still `extern` it to your heart's content. As such, there is nothing inherently "non-global" about `const` objects. – Lightness Races in Orbit Jun 02 '15 at 13:14
-
@Lightness Races in Orbit. `#define SETBITS(s,bv,m) (((s) & ~(m)) | ((bv) & (m)))` why should I use something like this as function? (I speak about C, but I think also C++) – Sir Jo Black Jun 02 '15 at 13:15
-
-
@SergioFormiggini: You shouldn't. Granted, I really am focusing on C++, in which you can `constexpr` the crap out of that and get the same result with none of the downsides. I'm not qualified to outright state that the benefits of an inline function outweigh potential performance concerns in C. Frankly, though, I'd be astounded. – Lightness Races in Orbit Jun 02 '15 at 13:16
-
-
-
@SergioFormiggini He's pointing out that while `SETBITS(s, bv, m++)` looks legitimate, it will actually cause problems due to it being a macro rather than a function. – JorenHeit Jun 02 '15 at 13:18
-
1@SergioFormiggini: If you call `SETBITS` in the manner Jack showed... actually, let's change that a bit to make it clearer. Call it as `SETBITS(x,y,z++)`. Now, since that third argument (called `m` inside the definition) is evaluated twice inside the macro, you end up with `z++` evaluated twice, which is almost certainly not what you wanted. Macros are full of pitfalls like this. Sure, you can work around them and avoid them, but then why bother with the pain in the first place? Just write a proper function and be done with it. – Lightness Races in Orbit Jun 02 '15 at 13:18
-
-
-
Yes, but is not the matter of my question. The matter is that if I use a call for that code the compiler should not optimize the code. Then, If an user uses a #define such that have to understand the issues it may create. Furthermore the use of that macro hardly should use m++ .... – Sir Jo Black Jun 02 '15 at 13:21
-
All literals have a type. It is impossible to `#define` a constant which isn't a literal and therefore all `#defines` do have a type. It is just less obvious which type they are. – Lundin Jun 02 '15 at 13:22
-
1This answer is not correct, since it is a C++ only anwer. The question is also tagged C, co a correct answer should take the completely different situation for C and for code that interfaces both languages into account. – Jens Gustedt Jun 02 '15 at 13:22
-
@Lundin: The name `SETBITS` does not have a type. Of course the expression to which it ultimately evaluates does. – Lightness Races in Orbit Jun 02 '15 at 13:22
-
The type doesn't care in that contest. Is a macro to set bits with a mask ... the user should know the bit operations are better accomplished using unsigned int ... If you pass something different you'll have (probably) undefined behaviour. But that code has a good chance of very good optimization. – Sir Jo Black Jun 02 '15 at 13:25
-
@LightnessRacesinOrbit "It is impossible to `#define` a constant which isn't a literal". Function-like macros is another thing entirely, they are just icky text replacement with no type safety. But the question is about the difference of defined constants and const variables, not about the difference between function-like macros and functions. – Lundin Jun 02 '15 at 13:28
-
@LightnessRacesinOrbit because it uses properties of `const` qualified variables that only hold for C++ and not for C. As you say, C doesn't seem to be your strong point, so don't claim something for it. – Jens Gustedt Jun 02 '15 at 13:28
-
@JensGustedt: I added a notice to the answer following our discussion under the question. That still doesn't make this answer flat-out _wrong_. – Lightness Races in Orbit Jun 02 '15 at 13:29
-
@JensGustedt: Wow, no need to attack my credentials/skills. I missed one fact about a complex language. How rude. – Lightness Races in Orbit Jun 02 '15 at 13:29
-
-
@LightnessRacesinOrbit, let's state it like that, you missed half of the answer for the question and insisted for quite a while that this is correct. I found *that* rude, so we are even. – Jens Gustedt Jun 02 '15 at 13:34
-
@Jens: Good grief. Now you're bandying about the accusations, but I notice you cast the first close-vote, shutting down this question as an "exact duplicate" of one _that focuses only on C_. What's that, you say? "Only half the question"? Yes, indeed; your rabid anti-C++ biases are showing. – Lightness Races in Orbit Jun 02 '15 at 13:35
-
@JensGustedt Pardon my ignorance, but what exactly are the C++ specific properties of `const` qualified variables mentioned in this anwer? – JorenHeit Jun 02 '15 at 13:44
-
@JorenHeit: http://stackoverflow.com/questions/30596943/what-is-the-benefit-of-using-define-to-declare-a-constant/30597115?noredirect=1#comment49263324_30596943 (he's not wrong) – Lightness Races in Orbit Jun 02 '15 at 13:50
-
@LightnessRacesinOrbit Thanks, I'll look into it. I wasn't suggesting he's wrong by the way. Just interested :-) **Edit:** seems like you accidentally pasted the link to this very question... **Edit2:** whoops got it. Sorry – JorenHeit Jun 02 '15 at 13:54
-
@LightnessRacesinOrbit, yes I voted to close it, but not because it was a duplicate. The SO attributes my close reason to the "majority" reason, a recent change in the system that I still find a bit weird. – Jens Gustedt Jun 02 '15 at 19:07
What is the benefit of using #define to declare a constant?
Declaring a constant with #define
is a superior alternative to using literals and magic numbers (that is, code is much better off with a value defined as #define NumDaysInWeek (7)
than simply using 7
), but not a superior alternative to defining proper constants.
You should declare a constant instead of #define
-ing it, for the following reasons:
#define
performs a token/textual replacement in the source code, not a semantic replacement.This screws up namespace use (#defined variables are replaced with values and not containing a fully qualified name).
That is, given:
namespace x { #define abc 1 }
x::abc
is an error, because the compiler actually tries to compilex::1
(which is invalid).abc
on the other hand will always be seen as 1, forbidding you from redefining/reusing the identifier abc in any other local context or namespace.#define
inserts it's parameters textually, instead of as variables:#define max(a, b) a > b ? a : b; int a = 10, b = 5; int c = max(a++, b); // (a++ > b ? a++ : b); // c = 12
#define
has absolutely no semantic information:#define pi 3.14 // this is either double or float, depending on context /*static*/ const double pi = 3.14; // this is always double
#define
makes you (the developer) see different code than the compilerThis may not be a big thing, but the errors created this way are obscure, unexpected and waste a lot of time (you could look at an error, where the code looks perfectly fine to you, and curse the compiler for half a day, only to discover later, that one of the symbols in your expression actually means something completely different).
If you get with a debugger to code using one of the declarations of
pi
above, the first one will cause the debugger to tell you thatpi
is an invalid symbol.
Edit (valid example for a local static const variable):
const result& some_class::some_function(const int key) const
{
if(map.count(key)) // map is a std::map<int,result> member of some_class
return map.at(key); // return a (const result&) to existing element
static const result empty_value{ /* ... */ }; // "static" is required here
return empty_value; // return a (const result&) to empty element
}
This shows a case when you have a const value, but it's storage needs to outlast the function, because you are returning a const reference (and the value doesn't exist in the data of some_class). It's a relatively rare case, but valid.

- 26,809
- 3
- 46
- 82
-
Don't do `static const`! You should always, always write `const double pi = 3.14` rather than `static const double pi = 3.14`. Adding the static forces it to have actual storage which then has to be accessed to get the number, rather than being able to insert the number where it is evaluated into the assembly; this needlessly slows your code down for no gain. – Jack Aidley Jun 02 '15 at 13:21
-
1Although, that might be different in C and C++, come to think of it. – Jack Aidley Jun 02 '15 at 13:23
-
@JackAidley: I have not heard about that. Can you provide some documenting evidence? I would actually expect a `static const` to be _more likely_ to get inlined everywhere. – Lightness Races in Orbit Jun 02 '15 at 13:24
-
@JackAidley That's nonsense, variables declared at file scope always have static storage duration, no matter if they are `static` or not. Therefore all file scope variables _should_ be declared as `static` if no other file needs them, to prevent them from cluttering down the global namespace. Local variables is another matter, declaring them as static will indeed move them to `.data` section rather than getting pushed on the stack. But of course the C standard does not require nor guarantee that. – Lundin Jun 02 '15 at 13:32
-
@JackAidley, you shouldn't _always_ write `const` instead of `static const`. I will edit my post for a counterexample. – utnapistim Jun 02 '15 at 13:35
-
@Lundin: `const` variables defined with no scope specifier don't have global scope anyway (in C++, I'm not sure about C), adding `static` makes no difference to that. – Jack Aidley Jun 02 '15 at 13:47
-
@utnapistim: Ah, `static` and it's wildly different set of meanings! Yes, local `static` can be appropriate in some circumstances. – Jack Aidley Jun 02 '15 at 13:48
-
2@JackAidley Eh... okay so this is why all "C/C++" questions should be closed as unclear. Just found this in C++03: "`Change: A name of file scope that is explicitly declared const, and not explicitly declared extern, has internal linkage, while in C it would have external linkage`". So this is quite different between the two languages. – Lundin Jun 02 '15 at 13:57
According to the "father" of C++, Stroustroup, defining constants using macros should be avoided.
The biggest Problems when using macros as constants include
- Macros override all occurrences in the code. e.g. also variable definitions. This may result in compile Errors or undefined behavior.
- Macros make the code very difficult to read and understand because the complexity of a macro can be hidden in a Header not clearly visible to the programmer

- 2,827
- 2
- 18
- 34
-
3In my opinon the father of c++ is the reason for a very ugly language to exist, I am going to read what you posted as a link which is not an answer. – Iharob Al Asimi Jun 02 '15 at 13:09
-
1I agree that the source is questionable... but even if it wasn't, link-only answers are discouraged at SO and will get deleted. – Lundin Jun 02 '15 at 13:20