"#define" vs "const int"

E

Eric

I'm told that with most optimizing compilers, if you say "const int
foo = 4" rather than "#define foo 4", the compiler won't actually
allocate any memory for the int. True?
 
B

Bo Persson

Eric said:
I'm told that with most optimizing compilers, if you say "const int
foo = 4" rather than "#define foo 4", the compiler won't actually
allocate any memory for the int. True?

Yes, but does it matter? How much space does a single number use?


Bo Persson
 
P

Pascal J. Bourguignon

Bo Persson said:
Yes, but does it matter? How much space does a single number use?

Even worse, some modern processors (eg RISC processors) just don't
have large immediates, so they will have to allocate memory for the
constants outside of the code anyways (or else use several
instructions to fill a register with a large value).


So you really don't want to think about these matters. Just write:
const int foo=4; since that's what the language provides you, and
since it gives more information than #define foo 4 to the compiler,
chances are it will be able to generate more optimized code, but you
shouldn't care.
 
E

Eric

So you really don't want to think about these matters. Just write:
const int foo=4; since that's what the language provides you, and
since it gives more information than #define foo 4 to the compiler,
chances are it will be able to generate more optimized code, but you
shouldn't care.

Good afternoon, Pascal.

This is a small system with limited memory, so yeah, we do have a
minor concern about every byte.

Thanks to all for the info...
 
B

Bill

Eric said:
I'm told that with most optimizing compilers, if you say "const int
foo = 4" rather than "#define foo 4", the compiler won't actually
allocate any memory for the int. True?

No one mentioned (I think) that #define is a "pre-processor directive".
The substitution of "4" for "foo" is made before the "real compilation" even
starts. Hence, no bytes for foo!

Bill
 
E

Eric

No one mentioned (I think) that #define is a "pre-processor directive".
The substitution of "4" for "foo" is made before the "real compilation" even
starts. Hence, no bytes for foo!

Good afternoon, Bill.

Right, I knew that (#define doesn't allocate memory). Just wasn't
sure if most optimizing compilers did the same with const int foo.
 
B

Bill

Eric said:
Good afternoon, Bill.

Right, I knew that (#define doesn't allocate memory). Just wasn't
sure if most optimizing compilers did the same with const int foo.

I few months ago I was experimenting with the latest MS VC++ compiler
(default settings).

I used a pointer and const_cast to change the value of a const int foo=5,
say to the value 7. The program continued to use the value 5 for foo,
except when I accessed the value of foo via the pointer, then the value was
7. Hence, I deduced, memory was allocated for foo, but the compiler
"optimized away" dynamic references to it. Consider trying it youself and
sharing what happens!

Bill
 
J

joecook

I used a pointer and const_cast to change the value of a const int foo=5,
say to the value 7.  The program continued to use the value 5 for foo,
except when I accessed the value of foo via the pointer, then the value was
7.  Hence, I deduced, memory was allocated for foo, but the compiler
"optimized away" dynamic references to it.  Consider trying it youself and
sharing what happens!

gcc 4.2.4 promptly gives a segmentation fault. It allocated memory
for the global constant, but it is clearly not at an address that is
writable by the running program.

Joe Cook
 
E

Erik Wikström

I few months ago I was experimenting with the latest MS VC++ compiler
(default settings).

I used a pointer and const_cast to change the value of a const int foo=5,
say to the value 7. The program continued to use the value 5 for foo,
except when I accessed the value of foo via the pointer, then the value was
7. Hence, I deduced, memory was allocated for foo, but the compiler
"optimized away" dynamic references to it. Consider trying it youself and
sharing what happens!

And most likely it would optimise away the allocated memory also,
provided that you do not take the address of the constant.
 
P

Pavel

Eric said:
Good afternoon, Pascal.

This is a small system with limited memory, so yeah, we do have a
minor concern about every byte.

Thanks to all for the info...
If so, and you do not really need to take an address of this constant
anywhere, I would think of using an unnamed enumeration. It would give
you both compiler support for your constant and no memory overhead (of
course, subject to the fact the immediate operands of required size are
supported at your system):

enum { foo = 4 };

-Pavel
 
J

James Kanze

On 2008-12-30 11:28:46 -0500, (e-mail address removed) (Pascal
J. Bourguignon) said:
What additional information does it give the compiler?
Obviously, unlike a manifest constant, the code could take its
address, but that inhibits rather than enhances optimization.

The issue isn't so much one of additional information; the
#define doesn't have scope, so introduces the issue of name
conflicts. Without that, it would probably be preferable
because, as you say, it prevents taking the address.

Sort of---the most frequent way the address ends up being taken
is because the constant is passed to a function taking a const
reference, e.g. something like std::vector<>::push_back. And
this will work with a #define as well; the compiler will
generate a temporary, and take its address. Typically, the
compiler will generate a new, on stack temporary for each such
use---whether this is an optimization or a pessimization depends
on the machine, and what your concerned about optimizing. (It
will almost certainly be a pessimization with regards to
runtime, and an optimization with regards to use of static
memory.)
 
R

Rolf Magnus

Pete said:
Yes, eveyone knows that macros are evil. But they're not as evil as
everyone thinks they are.

It doesn't matter much how "evil" they are. If there is a better way to do
the same, then why not use that? Macros are only used as replacements for
constants because people are used to that from C, which lacks support for
real constants. Otherwise, nobody would even think about using a macro for
that.
 
T

tni

Erik said:
And most likely it would optimise away the allocated memory also,
provided that you do not take the address of the constant.

If you look at the assembly code, VS uses immediate values for both
defines and const. If you take the address, it creates a stack temp.
 
R

Rolf Magnus

Pascal said:
Even worse, some modern processors (eg RISC processors) just don't
have large immediates, so they will have to allocate memory for the
constants outside of the code anyways (or else use several
instructions to fill a register with a large value).

Yes. The funny part is that in this case, a normal const int wouldn't be
optimal either. If the constant is used in multiple translation units, a
separate instance of the constant is needed for each of them. So it would in
such save memory if you mark the constant as extern.
 
C

Cédric Baudry

Hmm, technically correct about "foo" itself. However, the amount of memory
used by the program might be higher with the #define depending on how
it is later used. E.g. (already hinted by James)

#include <vector>

int const foo = 4;
#define FOO 4

void bar()
{
std::vector<int> v;
v.push_back(foo);
v.push_back(FOO); //will translate to v.push_back(int(FOO));
v.push_back(foo);
v.push_back(FOO); //a second temporary will be allocated

}

This is even worse:

#include <string>
#include <vector>

std::string const foo = "this a a constant string";
#define FOO "this is a macro string"

void bar()
{
std::vector<std::string> v;
v.push_back(foo);
v.push_back(FOO); //i.e. v.push_back(std::string(FOO));
v.push_back(foo);
v.push_back(FOO); //a second temporary will be allocated

}

Yan

Ok, so the define can cause infinitely more memory consuption than 0.

You seem to say that "this a a constant string" doesn't suffer the
same problem. Is it true for VC++2008 ?

What about the const. Does it cause exacly the same problem here or in
similar cases ?
 
C

Chris Gordon-Smith

This seems to be an unnecessarily absolutist point of view. It is true that
in many cases macros are not the best approach. However, they do have their
place. Include guards for example.

Chris Gordon-Smith
www.simsoup.info
 
T

Tony

Rolf Magnus said:
It doesn't matter much how "evil" they are. If there is a better way to do
the same, then why not use that? Macros are only used as replacements for
constants because people are used to that from C, which lacks support for
real constants. Otherwise, nobody would even think about using a macro for
that.

"Better" is subjective. I don't consider using a #define for a constant a
"macro". That said, I recently started using consts instead of #defines, but
it really is a miniscule thing relative to other things. I did notice that
while a #define "worked" everywhere, with consts sometimes there are integer
width and sign warnings. I started using consts because I figure it doesn't
involve a lot of compiler machinery to implement and I have well defined and
evolved uses of the preprocessor and don't see any benefit to keeping that
"functionality" there. All in all, it's such a trivial point in most cases.

Tony
 
C

Chris Gordon-Smith

Pete said:
Please be more careful with attributions. There is nothing in the
quoted text that I wrote.

And please be more sensitive to irony.

Perhaps I came to the thread rather late and didn't spot the irony. I did
notice that you had posted quoted text adding only "<g>", but didn't get
the significance. Perhaps you were re-posting to draw attention to a quote
that you thought made your point for you by the extreme way in which it was
stated.

A careful reader could have counted ">" characters to see that the text in
my post was a quote of a quote, rather than your original text.

Anyway, no offence was intended and I apologise if any was caused.

Chris Gordon-Smith
www.simsoup.info
 
P

Pascal J. Bourguignon

Chris Gordon-Smith said:
This seems to be an unnecessarily absolutist point of view. It is true that
in many cases macros are not the best approach. However, they do have their
place. Include guards for example.

The problem being with #include in the first place!

Now the problem with cpp macros and directives is that they are
textual, they work at the level of the characters. Hence the
preventions we have against their indiscriminate use. Moreover,
they're not powerful enough to do anything really useful (well, if you
add an external loop, cpp macros become Turing Complete, but they're
not much more expressive than a Turing Machine either).



But that doesn't mean that macros in general are bad. For example, in
lisp, macros are very good. But lisp macros don't work at the level
of the source text, but at the level of the syntactic tree.
 
T

Tony

blargg said:
The compiler/preprocessor does. Here are some problems with macros
used for constants.

A macro does general text replacement:

#define foo 1

struct bar { int foo; }; // error

Yes, sharp knives must be handled with care. Your above example is not
really a macro weakness, it's careless or naive programming is all.
Standards discipline are important and a bit of experience wouldn't hurt
either.
Expression must be parenthesized:

#define foo 1+1

int i = foo * 2; // unexpected result

Another example of a sharp knife being used by a child.
Avoiding name clashes by using convention of all-uppercase is ugly:

#define FOO 1 // ugly name

Yes, that example is ugly. But I don't find the following ugly at all:

#define MEM_PAGE_SIZE 4096

*One can even add some little trinket in the name to "ensure" uniqueness if
dealing with external code.
Macros aren't scoped:

void f1()
{
#define FOO 1
}

void f2()
{
#define FOO 2 // error, redefinition
}

No one in their right mind would do that and expect scoping! Again, you're
just showing untrained use of the preprocessor rather than inherent flaw
with text substitution. Sure, if the concept is difficult, avoid it. I don't
find it difficult at all.
Syntax differs from normal object declaration/initialization:

#define FOO 1
int bar = 1;

A minor point, but yeah, if one was just learning C (or teaching it!),
surely using 'const' is the way to go. But your examples seem to attempt to
make it look like the issues with defining constants via text substitution
are severe when they're really not. Note also that the preprocessor #define
That said, I recently started using consts instead of #defines,
but it really is a miniscule thing relative to other things.
[...]

Not if you use them in your library's header files, where they can
cause problems your client's code.

See the above response that I've asterisked to solve that simply.

Tony
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,061
Latest member
KetonaraKeto

Latest Threads

Top