-
#define vs. const
Hello,
I'm trying to understand the fundamental differences between define and const.
I tried :-
#include<iostream>
using namespace std;
#define num -2
const int NUMBER = -2;
int main()
{
int x = -NUMBER;
cout << "x = [" << x << "]\n";
int y = -num;
cout << "y = [" << y << "]\n";
return 0;
}
I'm getting on both occasions 2 as a result.
Can someone explain why you'd use const and not #define ?
Thanks,
Imanuel.
-
In your example, either way is fine.
If you use a static const in a class definition, you have a name-scoped constant: MyClass::MyConstant.
If you use a #define, you end up with no name-space scoping: you just have MyConstant.
This can lead to name collisions in code that includes the class definition.
-
Defines are a pre-processor macro, of the simplest sort, which replace every token with the constant value. It is exactly the same as using a constant value in the code... for example
#define three 3.0
foo(three);
foo(3.0);
both of the calls to foo are exactly the same -- they will create the same assembly language code. The macro is useful if it is used many times and you want to change the value in one place to affect many uses.
const float three = 3.0; is very different. It is strongly typed for c++ and you know it is a float (without a suffix, the 3.0 might really be a double!). You can take its address, should your function require a pointer to a float instead. It is the "better" way to do a constant, however there can be a bit of bloat attached to it (the macro is pure and cannot create bloat if you have a suffix, leaving the suffix off can create casting bloat) depending on how smart your compiler is and how you used it.
-
the following really brings home that the compiler, or at least visual c++, creates a full on float and the associated bloat of memory reads, writes, etc.
The following prints 2.0 in .net 2005:
#define three 3.0;
const float th = 3.0;
float * fp;
fp = (float *)& th;
fp[0] = 2;
printf("%f\n", th); //2.0
Note that trying to do similar hacks to the macro are impossible -- you cannot take the address of a macro constant, it is the pure thing and hopefully the constant is wired into the assembly language without the extra memory access etc (you never know, some compiler could make a mess here).
-
#define as a macro concept can hold a complete instructions,
for example you can :
Code:
#define Amahdy cout<<"Hello world";
main()
Amahdy
}
but of course you can't do the same thing with constants, as they only hold a value of a datatype or objeect , and never an instruction like this ...
and here is another example :
Code:
#define DevX "Hello World !"
#define Forums cout<<
main()
{
Forums DevX; //similar to cout<<"...";
//and use them anywhere else :
Forums "ByAmahdy !";
}
-
There are many differences between #defines and const. const is an object and you can take its address, for example. It's also type safe -- the compiler knows what the constant's type is. All these do not apply to #defines. In addition, you will find that some debuggers can't handle #defines properly so you won;t be able to print the name of the macro and see what it stands for.
Danny Kalev
-
Bjarne Stroustrup had commented somewhere about some issues in using #define (marcros). They are not always safe, and could lead to hard to find bugs, especially if the macro is in another file. I will give you a very simple example:
Code:
#include <iostream>
#define FIVE 2+3
const int five = 2+3;
using namespace std;
int main()
{
int TWENTYFIVE = FIVE * FIVE;
int twentfive = five * five;
cout<< TWENTFIVE <<endl;
cout<< twentfive <<endl;
return 0;
}
This is just one of the examples. Here if you change the macro to
#define FIVE (2+3)
there won't be any problem.
The fundamental difference is that macros are not compiled. Instead, the pre-processor replaces the occurances of the macro with the content. Ie, for the above example, the input to the compiler is actually:
Code:
#include <iostream>
const int five = 2+3;
using namespace std;
int main()
{
int TWENTYFIVE = 2 + 3 * 2 + 3;
int twentfive = five * five;
cout<< TWENTFIVE <<endl;
cout<< twentfive <<endl;
return 0;
}
The part in maroon is done by the pre-processor, and it is what the compiler gets.
Last edited by Razee Marikar; 11-16-2007 at 12:49 AM.
Reason: Correction of mistake (compiler expects instead of compiler gets)
-
But I showed you that const is not safe either, a simple pointer mistake in your code can re-value the constant forever... you can always find a way to claim something is "unsafe". Const is better, cleaner c++ code (always, always avoid a macro if you can!) -- but its not perfect and in embedded code the macro can be superior for some specialized reasons.
-
I am not saying that const is safe; nor that it is unmodifiable. But there are many many problems with #define s that it must be avoided when possible (like when you need a constant, use a const. When you need a constant in a class, use a static const, and so on), and that #define gives you result which you may find hard to debug. Agreed that 3.0f and 3.0 makes a big difference, but a C++ programmer ought to be aware of it. The problems associated with #defines are far less obvious, and most probably will be overlooked. If you do not try to take the address of a static const, an optimizing compiler may not allocate memory for it. I give one more example why #defines are unsafe. Check out the following code:
Code:
#include <iostream>
#define X 1;
#define Y 2;
using namespace std;
int main(void)
{
int a = X + Y;
cout << a << endl;
return 0;
}
At first look, many will expect this program to output 3. But the problem here is that like a statement in C++, a semi column was used for #define.
Similar Threads
-
By Ranger in forum VB Classic
Replies: 3
Last Post: 05-29-2006, 09:43 PM
-
By Ranger in forum VB Classic
Replies: 0
Last Post: 12-09-2000, 12:21 PM
-
By Julian Milano in forum VB Classic
Replies: 2
Last Post: 08-11-2000, 12:11 PM
-
By Julian Milano in forum VB Classic
Replies: 0
Last Post: 08-10-2000, 09:16 PM
-
By Kunal Sharma in forum VB Classic
Replies: 2
Last Post: 04-25-2000, 03:45 PM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
Forum Rules
|
Top DevX Stories
Easy Web Services with SQL Server 2005 HTTP Endpoints
JavaOne 2005: Java Platform Roadmap Focuses on Ease of Development, Sun Focuses on the "Free" in F.O.S.S.
Wed Yourself to UML with the Power of Associations
Microsoft to Add AJAX Capabilities to ASP.NET
IBM's Cloudscape Versus MySQL
|
Bookmarks