66

It's a simple question, but why would someone use #define to define constants?

What's the difference between

#define sum 1 and const int sum = 1;

Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 30
    I'm honestly really tempted to say, "because they're n00bs"... +1 good question – user541686 Jun 08 '11 at 03:55
  • wow , how can i find-out which is right , complicated answers :? –  Jun 08 '11 at 04:01
  • 2
    Yeah this one should bring out some amusing answers – Nemo Jun 08 '11 at 04:02
  • 3
    @user Very simple, if you're programming in C++ -- just follow Scott Meyer's advice Item#1 'Prefer const and inline to #define'. Use '#define' as a last resort where const would not work. For example, header inclusion guards etc. – greatwolf Jun 08 '11 at 04:05
  • @user: You are dangerously close to asking a religious question – Nemo Jun 08 '11 at 04:05
  • 6
    Here's a tip to reduce the risk of getting many disparate answers: don't ask a question in a title and a different question in the body. They're similar, but have different ways to answer. – R. Martinho Fernandes Jun 08 '11 at 04:05
  • 1
    @Nemo of course, how else can he rack up some rep points real quick? :P – greatwolf Jun 08 '11 at 04:08
  • Guys what should i do , is AndreyT answer true , i don't know the rules yet but more points for an answer means it's right !? –  Jun 08 '11 at 04:24
  • @Hamed: The up/downvote ratio is by no means authoritative, but it's the opinion of the majority and as such it's as good an indication for correctness as you can get on SO. (However, as @Victor pointed out, in this case it agrees with the very first advice in Scott Meyers' widely acclaimed book. That's an even better indication.) – sbi Jun 08 '11 at 07:20
  • Have you ever heard of the `enum` option? In my answer, I try to illustrate it. – Wolf Apr 27 '23 at 11:41

10 Answers10

50

#define has many different applications, but your question seems to be about one specific application: defining named constants.

In C++ there's rarely a reason to use #define to define named constants.

#define is normally widely used in C code, since C language is significantly different from C++ when it comes to defining constants. In short, const int objects are not constants in C, which means that in C the primary way to define a true constant is to use #define. (Also, for int constants one can use enums).

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 1
    @AndreyT man i am scared here :| , what's the rule is this true answer , cause of points ? –  Jun 08 '11 at 04:20
  • 3
    @user788552 more points to an answer doesn't mean it's true always – Synxmax Jun 08 '11 at 04:46
  • static const int and enum {...} are real constant constants in C++ – CygnusX1 Jun 08 '11 at 05:40
  • @CygnusX1: In C++ there's no need for `static` in front of `const int`. In C++ `const` objects have internal linkage by default. – AnT stands with Russia Jun 08 '11 at 05:51
  • *"`const int` objects are not constants in C"* - Wait, really? Why is that? – BlueRaja - Danny Pflughoeft Jun 08 '11 at 06:11
  • 1
    @BlueRaja - Danny Pflughoeft: Well, just because the language is defined that way. In C language you cannot use `const int` object as `case` label, as bitfield size, as array size for non-VLA array specifically because `const int` objects are not constants in C. The term "constant" in C refers to literal constants (like `25`) and to enum members, but not to `const` objects. – AnT stands with Russia Jun 08 '11 at 06:36
  • @BlueRaja - Danny Pflughoeft: I have a more detailed explanation here http://stackoverflow.com/questions/2308194/shall-i-prefer-constants-over-defines/2308364#2308364 – AnT stands with Russia Jun 08 '11 at 06:38
45

No one should not!
Actually, One should prefer const int sum = 1; over #define sum 1 for a number of reasons:

Scope Based Mechanism:

#defines 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 mentioned in #2, while debugging #define would provide no help really.


Thus, to avoid the above situations const will be a better choice.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
7

For the example that you just gave, I would normally use a const. Except of course, the #define can be used for conditional compilation elsewhere:

#if SOME_DEFINE == 1
    // Conditional code
#endif

This is something you can't do with a const. If you don't need the value to be accessible from the preprocessor, I'd say use a const unless there's some reason why that's not possible. There's some stuff on this in the C++ FAQ lite, where they rightly point out that just because the preprocessor is "evil", it doesn't mean you'll never need it.

Sven
  • 21,903
  • 4
  • 56
  • 63
  • I wouldn't say that constant can't be used for conditional compilation. You can specialize a template for the constant. Take a look [here](http://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c/1505664#1505664) for instance. – Kirill V. Lyadvinsky Jun 08 '11 at 04:14
  • Yes, but I can't use that to conditionally #include depending on platform or something like that. So I'd say it can't be used for certain types of conditional compilation. ;) – Sven Jun 08 '11 at 04:18
  • 1
    I would use build system to make such sort of choices rather then `define`s. – Kirill V. Lyadvinsky Jun 08 '11 at 04:24
  • 1
    I'm not making any recommendation on how to do conditional compilation, I'm just pointing out one possible thing you can do with #defines that isn't (easily) accomplished with a const. – Sven Jun 08 '11 at 17:31
3

#define is necessary to make things like inclusion guards work, because C++ doesn't have a real module import system.

#define causes a literal textual substitution. The preprocessor understands how to tokenize source code, but doesn't have any idea what any of it actually means. When you write #define sum 1, the preprocessor goes over your code and looks for every instance of the token sum and replaces it with the token 1.

This has a variety of limitations: #define sq(x) x * x will not work right if you use it like sq(3+3); and using #define for a constant does not respect scope in any way, nor does it associate any kind of type with the constant. However, #define can be used (especially in combination with some other special stuff like the # and ## preprocessor operators) to do some magic that is otherwise not possible (except by manually doing what the preprocessor does).

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
2

Always try to use "const int", rather than #define.

Use #define, only when your preprocessor code might be read by another tool, and it's easier for it to go with the preprocessor, rather than to parse the language.

Also it's the only way to define something to be checked later by #if/#else/#endif

malkia
  • 1,389
  • 13
  • 12
1

From Introduction to programming with C++ which was written by Daniel Liang stated that:

When you define a constant using #define directive, the constant is not stored in memory.The constant will be replaced with a value by compiler. When you declare constant using const keyword, the constant is stored in memory just like variable.

If constant need to be used in multiple programs, use #define to define it in header file so it can be included in other program. If constant used only in one program, using const to declare is more efficient.

John Joe
  • 12,412
  • 16
  • 70
  • 135
1

Some people have a [misinformed] belief that macros are ensured to be 'real' constants and would be replaced as it is while generating the machine instructions. But modern compilers will ensure that the constant literals are treated the same way.

In simple words

#define sum 1  /*is pre processed*/

Which means, that sum doesn't exist after the preprocessing stage is finished.

const int sum = 1; /*is compiled/linked*/

Which means sum exists till the executable is made out of your program.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 3
    Doesn't answer the OP's question of why one is used over the other. (Don't wanna be harsh, but it really doesn't answer it, sorry.) -1 – user541686 Jun 08 '11 at 03:57
0

The first is a preprocessor directive, before the compiler compiles your code, it will go through and replace sum with 1. The second declares a variable in memory to hold that quantity. I'm sure it can be argued as to which is best, but the "const int" is probably more common in C++ (when it comes to numeric constants).

http://www.geekpedia.com/KB114_What-is-the-difference-between-sharpdefine-and-const.html

Synxmax
  • 2,226
  • 1
  • 22
  • 38
  • 1
    `const int` does not declare a variable in memory; the linked article is incorrect. – Don Reba Jun 08 '11 at 03:54
  • @Don: can't you do `const int sum = 1; const int* sum_ptr = ∑`? – R. Martinho Fernandes Jun 08 '11 at 03:55
  • Doesn't answer the OP's question of why one is used over the other. (Don't wanna be harsh, but it really doesn't answer it, sorry.) -1 – user541686 Jun 08 '11 at 03:57
  • 1
    "declare a variable in memory" probably isn't precise enough to be described as true or false, really. – Karl Knechtel Jun 08 '11 at 04:00
  • 1
    @Martinho Fernandes: C++ Standard 7.1.5.1.3: "A pointer or reference to a cv-qualified type need not actually point or refer to a cv-qualified object, but it is treated as if it does." Casting away const-ness and assigning to such a pointer or reference has undefined behaviour. – Don Reba Jun 08 '11 at 04:07
  • @Don: I haven't read the linked article. It is indeed incorrect when it says "memory is allocated for the constant". I'll side with Karl and claim "declaring a variable in memory" is vague enough to be considered correct :P – R. Martinho Fernandes Jun 08 '11 at 04:12
  • The important part is that `const int` declares a variable in _scope_. This is the main difference from a constant created with `#define`. Whether to assign the variable memory or not is up to the compiler. – Don Reba Jun 08 '11 at 04:25
0

The argument against const variables is already shown in iammilind's answer, compiling/linking performance concerns.

Defining integer constants by #define is a behavior I observe predominantly among older C developers and C++ developers who are actually old-school C developers or are guided by such to work non-invasively on older code bases.

Interestingly, the use of enum for the same purpose is often unknown. Whenever I have the opportunity, I convert groups of related #defines to enumerations. For named constants that do not belong to any group, I use nameless enumerations.

enum { sum = 1 };

This way, we get compile-time constants that work in C and C++.

Wolf
  • 9,679
  • 7
  • 62
  • 108
-1

const int is just an int that can't change. #define is a directive to the C preprocessor, which is much more than just for defining constants.

See here for more details: http://en.wikipedia.org/wiki/C_preprocessor

robbrit
  • 17,560
  • 4
  • 48
  • 68
  • 2
    Doesn't answer the OP's question of why one is used over the other. (Don't wanna be harsh, but it really doesn't answer it, sorry.) -1 – user541686 Jun 08 '11 at 03:56