Advertisement

#define vs const

Started by March 22, 2001 07:02 PM
23 comments, last by thuned 23 years, 10 months ago
>The compiler has an option of ignoring your inline functions, I >use macros where the code absolutely must be inserted there >(I''ll have to dig up an example, not sure where I put that >project anymore). I did a test a while ago, and inline >functions were slower that macros in MSVC until I changed the >Function Inlining setting to All Applicable. So evidently MSVC >was choosing to ignore my inlines.

You can always use __forceinline.

/McFly
That''s compiler specific, I want to one day port most of the code I make to Linux, and G++ isn''t going to like __forcinline. I try to stick to standard syntax (like avoiding __int64''s, et cetera).

"Finger to spiritual emptiness underlying everything." -- How a C manual referred to a "pointer to void." --Things People Said
Resist Windows XP''s Invasive Production Activation Technology!
http://www.gdarchive.net/druidgames/
Advertisement
Even __forceinline does not make the compiler inline all inline functions. Go read MSDN for the details.

Mike Roberts
aka milo
One of the big differences between const''s and define''s is that a const has an address but a define does not. This means that the following is legal:

const char ConstantA = 10;
char* CharPointer = &ConstantA

but this is not legal:

#define DefineA ((char)10)
char* CharPointer = &DefineA

This is because the compiler substitutes every reference to DefineA with 10 so in the last example you are actually writing:

char* CharPointer = &10;

which is illegal.

define''s are often used to declare flags. For example DirectX uses plenties of define''s for defining flags like DDERR_SURFACELOST and DDBLT_WAIT.

const''s are often used for declaring pointers that are not allowed to change during runtime. For example:

const char* ErrorMessage = "An error has occured!";

Hope this helps you!

-René

Real programmers don't document, if it was hard to write it should be hard to understand

const int number = 4;

will create a memory space for number, and the memory area where consts are placed could be different than where variables are stored. This is particularly useful in embedded systems and the like where your program will reside on a ROM chip.
Gee Brain, what we gonna do tonight?
const int number = 4;

will create a memory space for number, and the memory area where consts are placed could be different than where variables are stored. This is particularly useful in embedded systems and the like where your program will reside on a ROM chip.
Gee Brain, what we gonna do tonight?
Advertisement
In my first post I said, "#define and const compile to the same code." It should follow that memory is not (usually) allocated for a const type.

Example, the following program:
const int X = 4;
int main () { return X; }

...compiles to the following code (MSVC 6.0):
push 4
pop eax
ret 0

X is plainly used as a constant, not as a memory location holding a constant value.

It is legal to take the address of a constant. When you do so, and if you use that address in such a way that it can''t be compiled-out, MSVC creates a space for your constant in a "CONST SEGMENT". In this case, memory is allocated for the constant and your code size will be that much larger. However, if you only use the constant by value, memory space will not be allocated.
Three minor corrections to the thread:

Spartacus: Actually, in your example anyone can change the value of ErrorMessage, because ErrorMessage is a pointer. The string is const, but the pointer to it is not.

Example:


const char* ErrorMessage1 = "text1";
const char* const ErrorMessage2 = "text2";

int main()
{
ErrorMessage1 = "some other string"; // ok, pointer is not const
ErrorMessage2 = "some other string"; // error: pointer is const

return 0;
}



Anonypous Moster: Only global (and static) constants are stored in special memory - local const variables and data members values can be determined at run-time and thus they cannot be stored in read-only memory.

Stoffel: Technically, the #define name doesn't have a type, but the value does:


#define X "distance"
#define Y 1.0

const char x[9] = "distance";
const double y = 1.0;

int main()
{
const char c1 = X; // error: no conversion from char[9] to char
const char c2 = Y; // warning: possible loss of data

// Note the similarity when using the "better typed" versions
const char c3 = x; // error: no conversion from char[9] to char
const char c4 = y; // warning: possible loss of data

return 0;
}



While the numerical and character constants' values and types are well-defined in the language standard, the typing is not obvious to the programmer. So const's extra typing is still quite useful, even if it means the same thing to the compiler in most cases.


Now back to general discussion.

The "const" keyword serves two basic purposes: optimization and protection.

As Stoffel said, most compilers can catch the #define trick, and substitute the relevant C++ const behavior. So there really isn't much difference performance-wise for #define vs. global and static constants. However, the "const" keyword does allow the use of constant instances of user-defined types, which #define does not support.

The best use of the const keyword is to protect data (oddly enough). const_cast isn't guaranteed to work properly if you modify the object; it's only real use is to pass non-modifiable objects to functions that don't actually modify the object, but are not aware of the const keyword. This exists for compatibility with certain APIs and poorly written C++ code.

Declaring function parameters (pointers and references) as const dictates who can modify the object. This localizes bugs and generally leads to better design, and in the case of inlines, better optimization.

Declaring non-static member functions as const allows them to be called on an const object of that type. This is useful for querying the state of an object you aren't allowed to change, such as getting the number of characters in a constant string.

Declaring reference function parameters (references) as const allows them to refer to temporary objects. This is useful for both implicit and explicit conversion using a constructor call.


Proper use of const leads to cleaner, faster code.

Edited by - null_pointer on March 23, 2001 5:57:21 PM

Edited by - null_pointer on March 23, 2001 6:10:07 PM
const variables to not get memory space (on MSVC5/6 at least)- there was lengthy discussion about this some time ago (btw I was on the losing side )

They get stomped into the code as a #define would, but with scope & typechecking.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
quote:
Original post by Mucman

I have another question on the lines of this topic... why would you define macros when you could use inline functions? I had an assigment question where there was a define called :
#include #define max(a, b) (((a) > (b)) ? (a) : (b))#define min(a, b) (((a) < (b)) ? (a) : (b))int main(){   int x = 100;   int y = 99;   int z;   z = max(min(--x, y--), min(++y, x++));   cout << "x=" << x << " y=" << y << " z=" << z << endl;   return 0;}  


Now try changing the macros to inline functions and it will work properly...

I guess that doesn''t answer the question about when to use define macros, but it does show you when not to use them


"You don''t get wise with the sleep still in your eyes." - Neil Peart


First of all, the reason to use a macro is simple, Macro don''t have types. If I create an inline function for max and min instead of a macro, you will need to overload the function for every type you plan on using the function on where as if you create a macro, you create it once and you can use it with any type of variables.



Cyberdrek
Headhunter Soft
A division of DLC Multimedia
Resist Windows XP''s Invasive Product Activation Technology!
[Cyberdrek | ]

This topic is closed to new replies.

Advertisement