Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

"#define" vs "const int"

4 views
Skip to first unread message

Eric

unread,
Dec 30, 2008, 10:05:09 AM12/30/08
to

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?

Jeff Schwab

unread,
Dec 30, 2008, 10:18:56 AM12/30/08
to

Yes.

Bo Persson

unread,
Dec 30, 2008, 10:19:56 AM12/30/08
to

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


Bo Persson


Jeff Schwab

unread,
Dec 30, 2008, 10:23:59 AM12/30/08
to

Let me clarify: What you've written does not imply any run-time
overhead. If you need to take the address of the constant later in the
same translation unit (&foo), then it must (of course) have an address,
and the compiler likely will allocate some memory for it.

Pascal J. Bourguignon

unread,
Dec 30, 2008, 11:28:46 AM12/30/08
to
"Bo Persson" <b...@gmb.dk> writes:

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.

--
__Pascal Bourguignon__

Eric

unread,
Dec 30, 2008, 1:47:41 PM12/30/08
to
On Tue, 30 Dec 2008 17:28:46 +0100, p...@informatimago.com (Pascal J.
Bourguignon) wrote:

>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...

Pete Becker

unread,
Dec 30, 2008, 2:37:59 PM12/30/08
to
On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal J.
Bourguignon) said:

>
> 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.


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.


--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Jeff Schwab

unread,
Dec 30, 2008, 4:05:24 PM12/30/08
to
Pete Becker wrote:
> On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal J.
> Bourguignon) said:
>
>>
>> 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.
>
>
> 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.

It's not so much that "const foo" gives the compiler additional
information, but that the macro potentially hides information, e.g.
replacing all uses of the name "foo" within subsequent namespaces and
function definitions.

Bill

unread,
Dec 30, 2008, 4:23:35 PM12/30/08
to

"Eric" <answer.to...@nospam.com> wrote in message
news:k3ekl4t4hlh4odpm2...@4ax.com...

>
> 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


Eric

unread,
Dec 30, 2008, 4:37:55 PM12/30/08
to
On Tue, 30 Dec 2008 16:23:35 -0500, "Bill" <Bill_...@comcast.net>
wrote:

>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.

Pete Becker

unread,
Dec 30, 2008, 5:20:13 PM12/30/08
to

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

Bill

unread,
Dec 30, 2008, 5:37:34 PM12/30/08
to

"Eric" <answer.to...@nospam.com> wrote in message
news:i25ll4ljrb8lpnavh...@4ax.com...

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

Jeff Schwab

unread,
Dec 30, 2008, 6:11:52 PM12/30/08
to
Pete Becker wrote:
> On 2008-12-30 16:05:24 -0500, Jeff Schwab <je...@schwabcenter.com> said:
>
>> Pete Becker wrote:
>>> On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal J.
>>> Bourguignon) said:
>>>
>>>>
>>>> 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.
>>>
>>>
>>> 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.
>>
>> It's not so much that "const foo" gives the compiler additional
>> information, but that the macro potentially hides information, e.g.
>> replacing all uses of the name "foo" within subsequent namespaces and
>> function definitions.
>
> Yes, eveyone knows that macros are evil. But they're not as evil as
> everyone thinks they are.

You're entitled to your opinion, but the particular use given by the OP
is just insidious. Of course we all use the preprocessor for #include,
and FWIW, I do occasionally use it for very simple metaprogramming;
Boost.Preprocessor is phenomenal. I'm of the opinion that it ought to
be the last resort, though, rather than the first.

joe...@gmail.com

unread,
Dec 30, 2008, 6:21:41 PM12/30/08
to
On Dec 30, 5:37 pm, "Bill" <Bill_NOS...@comcast.net> wrote:
> 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

Erik Wikström

unread,
Dec 30, 2008, 6:55:13 PM12/30/08
to

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

--
Erik Wikström

Pavel

unread,
Dec 30, 2008, 11:04:39 PM12/30/08
to
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

James Kanze

unread,
Dec 31, 2008, 2:47:18 AM12/31/08
to
On Dec 30, 8:37 pm, Pete Becker <p...@versatilecoding.com> wrote:
> On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal
> J. Bourguignon) said:

> > 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.

> 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.)

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Rolf Magnus

unread,
Dec 31, 2008, 4:50:07 AM12/31/08
to
Pete Becker wrote:

> On 2008-12-30 16:05:24 -0500, Jeff Schwab <je...@schwabcenter.com> said:
>
>> Pete Becker wrote:
>>> On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal J.
>>> Bourguignon) said:
>>>
>>>>
>>>> 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.
>>>
>>>
>>> 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.
>>
>> It's not so much that "const foo" gives the compiler additional
>> information, but that the macro potentially hides information, e.g.
>> replacing all uses of the name "foo" within subsequent namespaces and
>> function definitions.
>
> 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.

tni

unread,
Dec 31, 2008, 5:30:43 AM12/31/08
to

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.

Pete Becker

unread,
Dec 31, 2008, 6:43:43 AM12/31/08
to

Sigh. Please note the comment that I replied to originally. I really
don't want to get into a pissing match about the merits of macros.

Pete Becker

unread,
Dec 31, 2008, 6:44:59 AM12/31/08
to
On 2008-12-31 02:47:18 -0500, James Kanze <james...@gmail.com> said:

> On Dec 30, 8:37 pm, Pete Becker <p...@versatilecoding.com> wrote:
>> On 2008-12-30 11:28:46 -0500, p...@informatimago.com (Pascal
>> J. Bourguignon) said:
>
>>> 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.
>
>> 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.

I understand that. I asked a specific question about a specific
comment, and I'm really not interested in the various random thoughts
that occur to people when someone says macro.

Yannick Tremblay

unread,
Dec 31, 2008, 8:18:19 AM12/31/08
to
In article <gje3h...@news2.newsguy.com>,

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

Rolf Magnus

unread,
Dec 31, 2008, 8:31:56 AM12/31/08
to
Pascal J. Bourguignon wrote:

> 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.

blargg

unread,
Dec 31, 2008, 9:13:57 PM12/31/08
to
Pete Becker wrote:
> Rolf Magnus said:
> > Pete Becker wrote:
> >> Jeff Schwab said:
> >>> Pete Becker wrote:

> >>>> Pascal J. Bourguignon said:
> >>>>> 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.
> >>>>
> >>>> 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.
> >>>
> >>> It's not so much that "const foo" gives the compiler additional
> >>> information, but that the macro potentially hides information, e.g.
> >>> replacing all uses of the name "foo" within subsequent namespaces and
> >>> function definitions.
> >>
> >> 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.
>
> Sigh. Please note the comment that I replied to originally. I really
> don't want to get into a pissing match about the merits of macros.

Can't you figure it out? Macros are EVIL. That means we CANNOT even
talk about them or think about their behavior. We must convert
everyone into a believer and ensure they never discuss macros, other
than to argue against all mention/use of them. Our minds are fragile,
and the moment we start to contemplate macros versus alternatives,
even if only hypothetically in order to shed light on other issues, we
will lose all discipline and plunge ourselves into pre-C++ darkness.

Pete Becker

unread,
Dec 31, 2008, 9:24:35 PM12/31/08
to
On 2008-12-31 21:13:57 -0500, blarg...@gishpuppy.com (blargg) said:

>
> Can't you figure it out? Macros are EVIL. That means we CANNOT even
> talk about them or think about their behavior. We must convert
> everyone into a believer and ensure they never discuss macros, other
> than to argue against all mention/use of them. Our minds are fragile,
> and the moment we start to contemplate macros versus alternatives,
> even if only hypothetically in order to shed light on other issues, we
> will lose all discipline and plunge ourselves into pre-C++ darkness.

<g>

Cédric Baudry

unread,
Jan 2, 2009, 5:14:49 PM1/2/09
to
On 31 déc 2008, 14:18, ytrem...@nyx.nyx.net (Yannick Tremblay) wrote:
> In article <gje3hn0...@news2.newsguy.com>,
>
> Bill <Bill_NOS...@comcast.net> wrote:
>
> >"Eric" <answer.to.newsgr...@nospam.com> wrote in message

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 ?

Chris Gordon-Smith

unread,
Jan 2, 2009, 7:23:08 PM1/2/09
to
Pete Becker wrote:

> On 2008-12-31 21:13:57 -0500, blarg...@gishpuppy.com (blargg) said:
>
>>
>> Can't you figure it out? Macros are EVIL. That means we CANNOT even
>> talk about them or think about their behavior. We must convert
>> everyone into a believer and ensure they never discuss macros, other
>> than to argue against all mention/use of them. Our minds are fragile,
>> and the moment we start to contemplate macros versus alternatives,
>> even if only hypothetically in order to shed light on other issues, we
>> will lose all discipline and plunge ourselves into pre-C++ darkness.

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

blargg

unread,
Jan 2, 2009, 11:12:48 PM1/2/09
to

Whoosh!

Tony

unread,
Jan 3, 2009, 12:41:43 AM1/3/09
to

"Rolf Magnus" <rama...@t-online.de> wrote in message
news:gjff8f$qo8$00$1...@news.t-online.com...

"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


blargg

unread,
Jan 3, 2009, 1:30:06 AM1/3/09
to
Tony wrote:
> I don't consider using a #define for a constant a "macro".

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


Expression must be parenthesized:

#define foo 1+1

int i = foo * 2; // unexpected result


Avoiding name clashes by using convention of all-uppercase is ugly:

#define FOO 1 // ugly name


Macros aren't scoped:

void f1()
{
#define FOO 1
}

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

Syntax differs from normal object declaration/initialization:

#define FOO 1
int bar = 1;


> 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.

Pete Becker

unread,
Jan 3, 2009, 8:09:43 AM1/3/09
to
On 2009-01-02 19:23:08 -0500, Chris Gordon-Smith
<use.a...@my.homepage> said:

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

And please be more sensitive to irony.

Chris Gordon-Smith

unread,
Jan 3, 2009, 5:16:06 PM1/3/09
to
Pete Becker wrote:

> On 2009-01-02 19:23:08 -0500, Chris Gordon-Smith
> <use.a...@my.homepage> said:
>
>> Pete Becker wrote:
>>
>>> On 2008-12-31 21:13:57 -0500, blarg...@gishpuppy.com (blargg) said:
>>>
>>>>
>>>> Can't you figure it out? Macros are EVIL. That means we CANNOT even
>>>> talk about them or think about their behavior. We must convert
>>>> everyone into a believer and ensure they never discuss macros, other
>>>> than to argue against all mention/use of them. Our minds are fragile,
>>>> and the moment we start to contemplate macros versus alternatives,
>>>> even if only hypothetically in order to shed light on other issues, we
>>>> will lose all discipline and plunge ourselves into pre-C++ darkness.
>>
>> 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.
>>
>
> 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


Pascal J. Bourguignon

unread,
Jan 5, 2009, 8:59:48 AM1/5/09
to
Chris Gordon-Smith <use.a...@my.homepage> writes:

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.

--
__Pascal Bourguignon__

Pete Becker

unread,
Jan 5, 2009, 9:44:38 AM1/5/09
to
On 2009-01-05 08:59:48 -0500, p...@informatimago.com (Pascal J.
Bourguignon) said:

Please be more careful with your attributions. I didn't write any of
the quoted text.

Tony

unread,
Jan 6, 2009, 1:01:32 AM1/6/09
to

"blargg" <blarg...@gishpuppy.com> wrote in message
news:blargg.h4g-03...@192.168.1.4...

> Tony wrote:
>> I don't consider using a #define for a constant a "macro".
>
> 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
<const> automagically avoids integer width errors/warnings.

>
>
>> 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


Triple-DES

unread,
Jan 6, 2009, 3:03:28 AM1/6/09
to
On 6 Jan, 07:01, "Tony" <t...@my.net> wrote:
[snip]

> A minor point, but yeah, if one was just learning C (or teaching it!),
> surely using 'const' is the way to go.

If you want to use your constant portably in a constant expression,
surely using #define is the way to go. Perhaps you meant to write C++
instead of C?

Rolf Magnus

unread,
Jan 6, 2009, 4:14:42 AM1/6/09
to
Tony wrote:

>> 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.

It is a macro weakness, usually referred to as "namespace pollution". And
no, it's not really careless programming if you use a library with thousands
of macro definitions and don't know all of them, and then suddenly you use a
name that is already defined as a macro somewhere deep down in a header.
Been there, done that.

>> 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.

Namespaces are a much more elegant way to do that. And it seems rather ugly
to put everything except the 'constants' in a namespace and use some prefix
for those instead.
Also, if a constant belongs to a specific class, I want to put it there.

>> 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!

Not with macros. But with a constant, I could.

>> 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.

If you're not interfacing with C code, I'd say it's always 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.

But all of those issues don't exist at all if you use constants.

> Note also that the preprocessor #define <const> automagically avoids
> integer width errors/warnings.

I don't see where that would really be useful.

blargg

unread,
Jan 6, 2009, 5:50:42 AM1/6/09
to
Tony wrote:
> "blargg" <blarg...@gishpuppy.com> wrote in message
> news:blargg.h4g-03...@192.168.1.4...
> > Tony wrote:
> >> I don't consider using a #define for a constant a "macro".
> >
> > 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.
[etc...]

Every one of the examples you replied to was in fact a characteristic of
macros. Many are avoidable with appropriate conventions, but that
doesn't negate that they exist. I intend on arguing technical facts
only, not opinions, because the latter have little value to others.
Technical facts best help one choose whether to use macros or
alternatives within a particular context. In my own usage of the
language, I don't consider features inherently bad or good. Each feature
simply has technical characteristics that must be considered in
comparison to the alternatives for a particular situation.

Yannick Tremblay

unread,
Jan 6, 2009, 7:32:44 AM1/6/09
to
In article <cacdfefd-fe84-4e98...@y1g2000pra.googlegroups.com>,

For multiple usage inside a single translation unit, "std::string const
foo" will be allocated once and passed to the vector as a const
reference. For FOO, a temporary std::string will be created for each
instance.

Test it on your compiler:

#include <string>
#include <iostream>

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

void bar(std::string const & in)
{
std::cout << in << " is at: ";
std::cout << &in << std::endl;
}

int main()
{
bar(foo);
bar(FOO);
bar(foo);
bar(FOO);

return 0;
}

This gives me:
This is a constant string is at: 0x8049f38
This is a macro string is at: 0xbf9bf000
This is a constant string is at: 0x8049f38
This is a macro string is at: 0xbf9bf008

Admitedly, this is a special example constructed to highlight that
"#define do not use memory and should be used for optimisation" is
incorrect. One could write an example showing the reverse but this
would only be relevant if someone was saying that you should always
use constants because they use less memory. I don't think anyone is
sayng that.

Reasons to use const are best summarised here:
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7

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

There are cases where the const will use more memory, there are cases
where the #define will be worse.

My point is that it is not true that #define use less memory. The
correct answer is (unfortunately) it depends. So anyone still using
#define for constants in C++ under the pretext that they use less
memory is lying to themselves and should learn a bit more about what
happens under the hood before trying to micro-optimise. Attempting to
reduce memory usage by using #define instead of const is IMO premature
optimisation. It is far complex than that. Attempting to
micro-optimise without understanding what you are doing is also very
dangerous. Unless you really undertand what happens, just use the
recommended techniques and accepted idioms and leave optimisation for
when and where it is needed.

Also although the #define itself is not allocated in free space /
heap, the macro gets replaced inside the code and must exist somewhere
possibly in the text/code part of the executable. This is not free
either.


Noah Roberts

unread,
Jan 6, 2009, 11:40:42 AM1/6/09
to
Tony wrote:
> "blargg" <blarg...@gishpuppy.com> wrote in message
> news:blargg.h4g-03...@192.168.1.4...
>> Tony wrote:
>>> I don't consider using a #define for a constant a "macro".
>> 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.

The preprocessor isn't a knife, it's a spork. A sort of catch all that
never quite works right but sometimes you're stuck with it.

Noah Roberts

unread,
Jan 6, 2009, 11:42:23 AM1/6/09
to
Rolf Magnus wrote:
> Tony wrote:
>
>>> 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.
>
> It is a macro weakness, usually referred to as "namespace pollution". And
> no, it's not really careless programming if you use a library with thousands
> of macro definitions and don't know all of them, and then suddenly you use a
> name that is already defined as a macro somewhere deep down in a header.
> Been there, done that.

Like the damn min/max macros in the windows header breaking the
numeric_limits function, just for a common example.

Noah Roberts

unread,
Jan 6, 2009, 11:46:18 AM1/6/09
to

Where it will then be copied. I you have a ref counted string then it's
no big deal, but that's platform specific.

For FOO, a temporary std::string will be created for each
> instance.

So? Created and destroyed in mere micro-moments. Not a big deal except
in very certain and rare conditions. You're not prematurely optimizing
are you?

Tony

unread,
Jan 7, 2009, 12:18:05 AM1/7/09
to

"blargg" <blarg...@gishpuppy.com> wrote in message
news:blargg.h4g-E4673...@sn-ip.vsrv-sjc.supernews.net...

> Tony wrote:
>> "blargg" <blarg...@gishpuppy.com> wrote in message
>> news:blargg.h4g-03...@192.168.1.4...
>> > Tony wrote:
>> >> I don't consider using a #define for a constant a "macro".
>> >
>> > 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.
> [etc...]
>
> Every one of the examples you replied to was in fact a characteristic of
> macros."

Context always matters. Dry facts and definitions are not very useful
without context. I personally know not to run the car engine in an enclosed
garage. I don't need a special car to help me not to do that.

Tony


Yannick Tremblay

unread,
Jan 7, 2009, 6:13:44 AM1/7/09
to
In article <hWW8l.429$PE4...@nlpi061.nbdc.sbc.com>, Tony <to...@my.net> wrote:
>
>
>Context always matters. Dry facts and definitions are not very useful
>without context. I personally know not to run the car engine in an enclosed
>garage. I don't need a special car to help me not to do that.

Yet some peoples get killed every years by car fume exhaust in enclosed
places...

Yannick Tremblay

unread,
Jan 7, 2009, 6:25:29 AM1/7/09
to
In article <49638ad9$0$31121$cc2e...@news.uslec.net>,

Noah Roberts <no...@nowhere.com> wrote:
>Yannick Tremblay wrote:
>> In article <cacdfefd-fe84-4e98...@y1g2000pra.googlegroups.com>,
>> Cédric Baudry <mr.cedri...@gmail.com> wrote:
>>> On 31 déc 2008, 14:18, ytrem...@nyx.nyx.net (Yannick Tremblay) wrote:
>>>> In article <gje3hn0...@news2.newsguy.com>,
>>>>
>>>> Bill <Bill_NOS...@comcast.net> wrote:
>>>>
>>>>> "Eric" <answer.to.newsgr...@nospam.com> wrote in message
>>>>> news:k3ekl4t4hlh4odpm2...@4ax.com...
>>>>>> 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!
>>>> 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)
>>>>

>>>> 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

>> For multiple usage inside a single translation unit, "std::string const


>> foo" will be allocated once and passed to the vector as a const
>> reference.
>
>Where it will then be copied. I you have a ref counted string then it's
>no big deal, but that's platform specific.
>
> For FOO, a temporary std::string will be created for each
>> instance.
>
>So? Created and destroyed in mere micro-moments. Not a big deal except
>in very certain and rare conditions. You're not prematurely optimizing
>are you?

????

Sorry but read the context of the thread and read my entire post. I
am replying in the context of the OP who indicate that he was told to
use #define because they use less memory. This is incorrect. Using
#define may use more or less memory than using const depending of the
exact code. BTW, most of the time, I agree, the potential difference
in memory usage between const and #define is going to be irrelevant.
So use the safer technique.

For reference, content of my previous message that you have cut:

Admitedly, this is a special example constructed to highlight that
"#define do not use memory and should be used for optimisation" is
incorrect. One could write an example showing the reverse but this
would only be relevant if someone was saying that you should always
use constants because they use less memory. I don't think anyone is
sayng that.

Reasons to use const are best summarised here:
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7

[...] Unless you really undertand what happens, just use the


recommended techniques and accepted idioms and leave optimisation for
when and where it is needed.

Yannick

blargg

unread,
Jan 7, 2009, 2:44:21 PM1/7/09
to

Yes, a practitioner combines the facts and context and makes decisions.
When discussing the tools themselves, it's often simpler to focus on
their characteristics only, without reference to context. Why cover x*y
combinations when you can cover the possible values of x and y
separately? See STL for another application of this approach.

Gerhard Fiedler

unread,
Jan 7, 2009, 5:35:08 PM1/7/09
to
On 2009-01-06 14:42:23, Noah Roberts wrote:

> Rolf Magnus wrote:
>> It is a macro weakness, usually referred to as "namespace pollution".
>> And no, it's not really careless programming if you use a library
>> with thousands of macro definitions and don't know all of them, and
>> then suddenly you use a name that is already defined as a macro
>> somewhere deep down in a header. Been there, done that.
>
> Like the damn min/max macros in the windows header breaking the
> numeric_limits function, just for a common example.

You know about the NOMINMAX macro, right?

Gerhard

Greg Herlihy

unread,
Jan 7, 2009, 6:15:45 PM1/7/09
to
On Jan 6, 4:32 am, ytrem...@nyx.nyx.net (Yannick Tremblay) wrote:
> In article <cacdfefd-fe84-4e98-855d-38b4342c3...@y1g2000pra.googlegroups.com>,

> Cédric Baudry <mr.cedric.bau...@gmail.com> wrote:
>
> Reasons to use const are best summarised here:http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
>
> >What about the const. Does it cause exacly the same problem here or in
> >similar cases ?
>
> There are cases where the const will use more memory, there are cases
> where the #define will be worse.

Yet no such cases -should- exist.

In other words, the choice between a const int variable or the
equivalent #define constant in a C++ should make no difference to
either the program's memory use or its performance. And if there is a
case where choosing between the two ways to specify a constant value -
really does have an effect on a compiled C++ program, then either it's
time to find a decent C++ compiler or to fix a hidden dependency bug
in the program.

Logically, if we compile the same program twice and produce two
builds, would we expect to find that one of the builds has better
performance or uses less memory than the other? Probably not. And yet,
that is exactly the situation described here: How after all, does
simply "replacing" an integer constant with the same integer constant
value do anything to change the program's logic? What will the program
do differently afterwards than it did before? (Nothing different, we
would hope). So, with no change to the program's logic, the program
built after the change is the same program - so there is no reason to
expect a different binary than the one build before.

In practice, there are no runtime benefits to be realized from using
#define constants instead of C++'s (better) alternatives. Consider
this code I copied from some else's post to this thread:

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
}

When optimizing bar(), gcc transforms its body into a loop - this loop
iterates four times and executes the same instruction (an immediate
store of the value "4" directly into the vector's storage) each time.
So an example meant to highlight the differences between the two types
of constants - can also be used to demonstrate that that whatever
their semantic differences might be - as far as this C++ program is
concerned, the four push_backs() statements really all do the same
thing.

Greg

Tony

unread,
Jan 8, 2009, 1:36:23 AM1/8/09
to

"blargg" <blarg...@gishpuppy.com> wrote in message
news:blargg.h4g-14BC1...@sn-ip.vsrv-sjc.supernews.net...

I still hold that context always matters.

Tony


Tony

unread,
Jan 8, 2009, 1:34:59 AM1/8/09
to

"Yannick Tremblay" <ytre...@nyx.nyx.net> wrote in message
news:12313268...@irys.nyx.net...

And still no "special car" to prevent that. Go figure? Feel free to put a CO
detector inside your car if you want to.

Tony


Yannick Tremblay

unread,
Jan 8, 2009, 4:04:47 AM1/8/09
to

Depends. Nowadays, factories use electric powered lift truck indoor
rather than petrol power one. Seems to me like a logical safety
improvement.

Yan

blargg

unread,
Jan 8, 2009, 5:04:24 AM1/8/09
to
Tony wrote:
> "blargg" <blarg...@gishpuppy.com> wrote in message
> news:blargg.h4g-14BC1...@sn-ip.vsrv-sjc.supernews.net...
> > Tony wrote:
[...]

> >> Context always matters. Dry facts and definitions are not very useful
> >> without context. I personally know not to run the car engine in an
> >> enclosed garage. I don't need a special car to help me not to do that.
> >
> > Yes, a practitioner combines the facts and context and makes decisions.
> > When discussing the tools themselves, it's often simpler to focus on
> > their characteristics only, without reference to context. Why cover x*y
> > combinations when you can cover the possible values of x and y
> > separately? See STL for another application of this approach.
>
> I still hold that context always matters.

There isn't a context if you're just discussing language features in the
abstract. Even toy examples don't establish a true context, since many
aspects of them are unspecified. But I'm sorry to say I think discussing
anything with you is going to be a waste of time, due to your discussion
tactics. :(

Tony

unread,
Jan 9, 2009, 1:04:14 AM1/9/09
to

"blargg" <blarg...@gishpuppy.com> wrote in message
news:blargg.h4g-08...@192.168.1.4...

> Tony wrote:
>> "blargg" <blarg...@gishpuppy.com> wrote in message
>> news:blargg.h4g-14BC1...@sn-ip.vsrv-sjc.supernews.net...
>> > Tony wrote:
> [...]
>> >> Context always matters. Dry facts and definitions are not very useful
>> >> without context. I personally know not to run the car engine in an
>> >> enclosed garage. I don't need a special car to help me not to do that.
>> >
>> > Yes, a practitioner combines the facts and context and makes decisions.
>> > When discussing the tools themselves, it's often simpler to focus on
>> > their characteristics only, without reference to context. Why cover x*y
>> > combinations when you can cover the possible values of x and y
>> > separately? See STL for another application of this approach.
>>
>> I still hold that context always matters.
>
> There isn't a context if you're just discussing language features in the
> abstract.

And I noted, that is not a good way to do that. That's why discussions about
EH and GC go round and round and never seem to end. Establish some context
and things get way simpler.

> Even toy examples don't establish a true context, since many
> aspects of them are unspecified. But I'm sorry to say I think discussing
> anything with you is going to be a waste of time, due to your discussion
> tactics. :(

Disagreeing with you is not "a tactic".

Tony


0 new messages