Sign in to follow this  
Evil Booger

What's the difference between #define and const int

Recommended Posts

Ok I have been through a lot of books and tutorials and they seem to use "#define" and "const int" interchangebly. So what's the difference? I know that #define is a preprocessor directive (or something like that), but does that really make a difference. Which one should I use?

Share this post


Link to post
Share on other sites
#define is clearly inferior to const T for defining regular compile-time constants. There are many reasons so I'll just mention some of the most important ones (EDIT: didn't see ToohrVyk's link, it mentions some other problems):

1) Doesn't work with namespaces.

2) May change other peoples' code. For instance:
#define NumScreens 8

void foo()
{
int NumScreens = Config::screens();
}

Here it's obvious that we'll cause problems, but imagine if you write library A with the #define, another person write library B without knowing about your library and uses the same name internally. A third user first includes library A then library B and he'll be greeted by an "unexpected token '8' after int" or something like that in some other person's library in a line which looks completely normal. This kind of stuff is fairly normal. For a real life example consider:
#include <windows.h>
void CreateWindow()
{
// Just a placeholder for now.
}
int main()
{
CreateWindow();
return 0;
}

windows.h is the primary file for the Win32 API and the code certainly doesn't look like it will cause problems yet, but here is what my compiler gives me:
------ Build started: Project: a, Configuration: Debug Win32 ------
Compiling...
main.cpp
x:\projects\a\main.cpp(2) : warning C4003: not enough actual parameters for macro 'CreateWindowW'
x:\projects\a\main.cpp(2) : error C2059: syntax error : ','
x:\projects\a\main.cpp(3) : error C2143: syntax error : missing ';' before '{'
x:\projects\a\main.cpp(3) : error C2447: '{' : missing function header (old-style formal list?)
x:\projects\a\main.cpp(8) : warning C4003: not enough actual parameters for macro 'CreateWindowW'
x:\projects\a\main.cpp(8) : error C2059: syntax error : ','

Why? Because someone thought it was a good idea to create a "#define CreateWindow ..." deep in the windows.h file (actually in files included by it).

3) Can give problems when the #define contains more than one term, for instance:
#define NUM_SYSTEM_PROCESSES 3
#define NUM_USER_PROCESSES 8
#define NUM_PROCESSES NUM_USER_PROCESSES + NUM_SYSTEM_PROCESSES

std::cout << "The number of processes on two systems is: " << 2*NUM_PROCESSES << "\n";

What would you expect? 2*11 if you haven't given it much thought. However it's a pure textual expansion so we actually get: 2*8+3 which is 19, not 22. Experienced C programmers remember to surround their constants with ( and ), but why would you want to remember this in C++?

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Booger
Ok I have been through a lot of books and tutorials and they seem to use "#define" and "const int" interchangebly. So what's the difference? I know that #define is a preprocessor directive (or something like that), but does that really make a difference. Which one should I use?


#define takes the text on the left and replaces it with the text on the right, before the compiler sees it.


// We see:
#define SOME_CONSTANT 12
#define X 32

void foo()
{
int i = SOME_CONSTANT;
}

int SomeClass::getX()
{
return x;
}

// compiler sees:


void foo()
{
int i = 12;
}

// it text replaces the X here too.
int SomeClass::get32()
{
return this->x;
}


As you can see this can result in unexpected consequences, for example if you had an int variable named uppercase X the compiler would generate an error:
int 32 = 32 ; // error

Const ints are better behaved.
The compiler sees const ints and will usually inline the values in exactly the same way, but it can never go wrong. For example, you can nest const ints in namespaces, class statics and functions, in a way that you cant with defined constants:

const int X = 1;

namespace somenamespace {
const int X = 2;

class SomeClass {
public:
static const int X = 3; // note static const integral values can be placed inside class declaration
// static consts of other types need seperate definitions
void foo();
};
}



Note all these "X" values are different and can be identified seperately.

void somenamespace::SomeClass::foo()
{
int one = SomeClass::X;
int two = somenamespace::X;
int three = ::X;
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this