"#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?
 
J

jacob navia

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?
lcc-win will do this. If you say

static const int foo = 4;

it will not allocate space for it. Otherwise it has to allocate space
since it could be used in some other module.
 
B

Ben Pfaff

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?

It would be tricky to do that if `foo' is either an object with
external linkage or an object whose address is taken. Otherwise,
this seems fairly likely.
 
S

Stephen Sprunk

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?

It's possible, but not guaranteed. If you take the address of foo, or
declare it in a way that gives it external linkage, the compiler cannot
eliminate it.

And, defying common sense, a "const int" is not a "constant integer
expression" in C, as it would be in C++, so it can't be used in some
places (e.g. a case statement in a switch) that the #define version can.
However, you do get the benefit of additional type checking, so IMHO
it's worth converting as many examples as you can.

S
 
K

Keith Thompson

Malcolm McLean said:
If you've got to worry about the space for an int then you are
probably on such a small system that I wouldn't bank on the compiler
doing any aggressive optimisations.

Such a small system would probably have a cross-compiler, not compiler
running on the system itself, so it would be free to do all the
agressive optimization it likes.
 
B

Ben Pfaff

jacob navia said:
lcc-win will do this. If you say

static const int foo = 4;

it will not allocate space for it. Otherwise it has to allocate space
since it could be used in some other module.

How does it do this, if the address of foo is taken?
 
F

Flash Gordon

Malcolm said:
But there's likely only a small market for it.

Or a large market if it is one of the popular embedded processors.
And embedded programmers
often like to see a one to one mapping between C source and assembly.

All the ones I've met wanted to see the fastest possible code produced
from their C sources, with the sole exception of where they used volatile.
 
E

Eric

But there's likely only a small market for it. And embedded programmers
often like to see a one to one mapping between C source and assembly.

Good afternoon, Malcolm and Keith.

Yes, this is a small system with limited memory. The compiler in use
is the IAR, which claims VERY aggressive optimization. Those who want
to see a one to one mapping between C and assembly can turn
optimization off. In fact, it's reported that sometimes the
optimization has to be turned off to get the debugger to work
correctly.
 
K

Keith Thompson

blargg said:
One common alternative to #define for int is enum. It's scoped and
doesn't require parenthesizing the entire expression. On the downside,
it's a distinct type, which might cause compiler warnings.

enum { foo = 4 };

The enum declaration creates a distinct type, but the literals are of
type int. So, for example, given:

enum e { foo = 4 };
enum e obj;

obj is of type "enum e", but foo is of type int.
 
C

CBFalconer

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?

I would expect that any such optimization would not be legal in C.
C++ is another matter, and I don't know the answer.
 
J

James Kuyper

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?

If you declare

const int foo = 4;

At block scope, and only use it in ways that would be legal with either
method, than a sufficiently good optimizing compiler will probably
generate essentially the same code with either approach.

However if you declare it at file scope, it will have external linkage.
The compiler must therefore set aside actual memory for 'foo', just in
case some other module in the same program contains code like the following:

extern const int foo;

const int *pi = &foo;

It would require pretty tight coupling between a compiler and a linker
to determine that there is no such module, and as a result remove the
object.
 
F

Flash Gordon

James said:
If you declare

const int foo = 4;

At block scope, and only use it in ways that would be legal with either
method, than a sufficiently good optimizing compiler will probably
generate essentially the same code with either approach.
True.

However if you declare it at file scope, it will have external linkage.

Usage within the same file is still likely to be optimed away.
The compiler must therefore set aside actual memory for 'foo', just in
case some other module in the same program contains code like the
following:

extern const int foo;

const int *pi = &foo;

It would require pretty tight coupling between a compiler and a linker
to determine that there is no such module, and as a result remove the
object.

It does not really require tight coupling between the compiler and
linker. The compiler can flag foo as defined but not used in the first
module, then the linker just has to remember if any other module refer
to it (and it needs to detect the references anyway to resolve them) and
eliminate it if it is not used. I don't know if any linkers actually do
this though.
 
C

CBFalconer

Ben said:

For example, there are ways of beating the 'const'
characterization, via pointers etc. They may be in other modules,
and thus totally undetectable. If this is not sufficient, or not
sufficiently illegal, there is also the problem of preventing it
and avoiding taking the address (which would not exist).
 
K

Keith Thompson

CBFalconer said:
For example, there are ways of beating the 'const'
characterization, via pointers etc. They may be in other modules,
and thus totally undetectable.

Anything that avoids the "const" qualification invokes undefined
behavior, and this is irrelevant to the question of whether the
optimization is legal.
If this is not sufficient, or not
sufficiently illegal, there is also the problem of preventing it
and avoiding taking the address (which would not exist).

Right, if the address is taken (and the code that takes the address
can't be optimized away), then space has to be allocated. But if the
compiler (or linker) can prove that the address is never taken, or if
any code that depends on the address can be optimized away, then the
object itself can be optimized away.
 
J

James Kuyper

CBFalconer said:
For example, there are ways of beating the 'const'
characterization, via pointers etc. They may be in other modules,
and thus totally undetectable. ...

Any such methods have undefined behavior; one permissible form for that
undefined behavior is for the use of those methods to fail to have any
effect on code making use of foo.
... If this is not sufficient, or not
sufficiently illegal, there is also the problem of preventing it
and avoiding taking the address (which would not exist).

He was talking about

const int foo = 4;

as a replacement for

#define foo 4

Code with defined behavior which uses the macro can't involve taking the
address of foo, so the issue never comes up.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top