Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


#define vs const


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
10 replies to this topic

#1 __SKYe   Members   -  Reputation: 1148

Like
0Likes
Like

Posted 08 June 2012 - 11:55 PM

Some time ago, i read somewhere (i think it was on an old C++ book, not sure) that one should use const instead of #define, the reason being that #define is a preprocessor directive, and if for some reason the compiler ignored it, error would occur.

Now maybe at the time, compilers weren't very safe, so this line of thought was understandable (i think).

But nowadays, i think it isn't so. Let me explain:

Defining a const variable (i know, const variable doesn't sound too good), ensures that variable always has the same value (or in case of pointers a 'ex. const <type> * const <name>', as in "constant pointer, constant value" (please correct me if i'm wrong). However it uses memory to declare this variable, and it works like any other variable (if somewhere in your program there's a reference to this const variable, the program will fetch it's value from memory.

On the other hand, #define is a preprocessor directive, so no memory will be used for that value, and when a defined value is found in a program, it will be replaced by the value at compile time, not run time.

So, i'm i right to think that #define is better than const, or am i wrong?

Post your thoughts, and do correct me if i'm wrong.

Thanks in advance.

Sponsor:

#2 Krohm   Crossbones+   -  Reputation: 3410

Like
0Likes
Like

Posted 09 June 2012 - 02:15 AM

For modern compilers, there's really little difference with regard to the code produced. They will mangle the expressions anyway.
Furthermore, let's say they really need to be allocated and you have like 1024 constants. I'm afraid most people would get crazy really soon but... you're trashing how much? 4 KiB. No one is going to have a problem. You're torturing yourself with a problem that might be relevant on a 100 Mhz 80486. I sincerely hope you don't own an i7.

#define is extremely more powerful than const but for the purpose of this discussion, we will suppose you can only use them to define constants.
To that regard, neither guarantees the identifier will be associated with the same value depending on the order in which source files are compiled.
Sure define is more problematic as it can be undefined and re-defined again. So not only we're not really sure what it holds, we cannot even take for granted it holds the intended value. At least const cannot be redeclared.

Personally I don't see why you should bother. Use const whathever possible. In most cases, this means use define to allocate constant-sized arrays inside structs ... and little else.

#3 DevFred   Members   -  Reputation: 836

Like
1Likes
Like

Posted 09 June 2012 - 02:27 AM

However it uses memory to declare this variable, and it works like any other variable (if somewhere in your program there's a reference to this const variable, the program will fetch it's value from memory.

The constant will only be placed into memory if you take its address or pass it by reference. For example:
#include <stdio.h>

const int answer = 42;

int main()
{
    printf("%d\n", answer);
}
turns into:
    .file    "floating.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string    "%d\n"
    .text
    .globl    main
    .type    main, @function
main:
.LFB31:
    .cfi_startproc
    subq    $8, %rsp
    .cfi_def_cfa_offset 16
    movl    $42, %edx
    movl    $.LC0, %esi
    movl    $1, %edi
    movl    $0, %eax
    call    __printf_chk
    movl    $0, %eax
    addq    $8, %rsp
    .cfi_def_cfa_offset 8
    ret
    .cfi_endproc
.LFE31:
    .size    main, .-main
    .ident    "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
    .section    .note.GNU-stack,"",@progbits
Note how the constant is placed directly into the code, and the variable answer got optimized away.

#4 apatriarca   Crossbones+   -  Reputation: 1864

Like
0Likes
Like

Posted 09 June 2012 - 04:25 AM

Using const you can have constants local to a function, namespace, class.. You can't do that using a #define and it can be very useful to have local constants.

#5 phantom   Moderators   -  Reputation: 8087

Like
2Likes
Like

Posted 09 June 2012 - 06:58 AM

Some time ago, i read somewhere (i think it was on an old C++ book, not sure) that one should use const instead of #define, the reason being that #define is a preprocessor directive, and if for some reason the compiler ignored it, error would occur.


The compiler wouldn't 'ignore' it because the compiler never saw it and there in lies the problem.

A #define is nothing more than a global text replace operation.
If you #define foo 1 then everywhere the preprocessor sees foo it replaces it with 1 with no concerns about scope nor context. This can lead to all manner of problems a classic example being the 'max' macro in the Windows headers.

If you include windows.h and then go on to try to use std::max() you'll get some lovely compiler errors spat out at you because 'max' is a #define provided by the windows.h header (or a decendant thereof) which replaces the 'max' portion of 'std::max' with some existing code.

This lack of scope is a double edged sword; on the one hand it does allow you to do global text replacement operations, on the other hand it stomps all over scope and has no regard for context.

In short; for constant variable declarations you should perfer the various C++ methods for declaring such things (const and constexpr in C++11), rather than #define, as those respect scope and are seen by the compiler.

#6 Bregma   Crossbones+   -  Reputation: 5765

Like
3Likes
Like

Posted 09 June 2012 - 06:59 AM

In C++, using preprocessor string substitution (#define) pollutes the global namespace. This can have serious consequences in larger projects.

Using const and constexpr in C++ allows the compiler's optimizer much greater leeway since it better knows data flows and can perform folding and hoisting to a much higher degree. This can have serious benefit in larger projects.

Using const values rather than preprocessor string substitution allows the programmer to take advantage of the strong typing of the C++ language rather than the weak typing of the C language. It helps you eliminate entire categories of hard-to-track-down bugs.
Stephen M. Webb
Professional Free Software Developer

#7 larspensjo   Members   -  Reputation: 1561

Like
0Likes
Like

Posted 09 June 2012 - 08:46 AM

There are cases where memory allocation from const may be a problem, and that is when it is done inside a class.

Don't forget the possibility to use "enum". This works excellently when declared inside classes.
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#8 Cornstalks   Crossbones+   -  Reputation: 6995

Like
0Likes
Like

Posted 09 June 2012 - 09:32 AM

Don't forget the possibility to use "enum". This works excellently when declared inside classes.

Or namespaces, if they don't belong in a class.

Bregma pretty much said what I wanted to say. If you use #defines to define constants, I hate you. Just use a friggin' consts or enums like you should be. Macros pollute the global namespace, which is completely unnecessary and can cause serious headaches when you have to mangle your own code just to work around someone else's laziness/stupidity. Also, their type is not explicit, and so you also don't get the benefit (or at least not as much of the benefit) of type safety, which is one of C++'s best points.

Your concern about memory is unfounded. They can (and should) be completely optimized away by the compiler. And if they're not, it's for a good reason. Trust your compiler.

Also, your comparison between const and macros fails. You mention storing a reference to a const (in which case, yes, the compiler will probably preserve that variable in memory), which isn't possible to do with a macro. You're comparing apples and oranges.

*note: I'm talking about compile-time consts here.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#9 Washu   Senior Moderators   -  Reputation: 6375

Like
2Likes
Like

Posted 09 June 2012 - 09:42 AM

Macros pollute the global namespace, which is completely unnecessary and can cause serious headaches when you have to mangle your own code just to work around someone else's laziness/stupidity.


No, they don't pollute any namespaces. The exist BEFORE all namespaces have even been determined. If it was just polluting the global namespace you could get around them, but since it comes before any namespace even exists, you're SOL.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
ScapeCode - Blog | SlimDX


#10 Cornstalks   Crossbones+   -  Reputation: 6995

Like
0Likes
Like

Posted 09 June 2012 - 09:45 AM

Macros pollute the global namespace, which is completely unnecessary and can cause serious headaches when you have to mangle your own code just to work around someone else's laziness/stupidity.


No, they don't pollute any namespaces. The exist BEFORE all namespaces have even been determined. If it was just polluting the global namespace you could get around them, but since it comes before any namespace even exists, you're SOL.

Yes, that's more technically correct. What's the best way to state that though/what's it technically called? I wasn't sure of how to name it, and "polluting the global namespace" is what came to mind, which I know is a misnomer.
[ I was ninja'd 71 times before I stopped counting a long time ago ] [ f.k.a. MikeTacular ] [ My Blog ] [ SWFer: Gaplessly looped MP3s in your Flash games ]

#11 __SKYe   Members   -  Reputation: 1148

Like
0Likes
Like

Posted 09 June 2012 - 04:10 PM

Thanks for all the answers!




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS