"#define" vs "const int"

T

Triple-DES

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

Rolf Magnus

Tony said:
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.
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.
No one in their right mind would do that and expect scoping!

Not with macros. But with a constant, I could.
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.
 
N

Noah Roberts

Tony said:
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.
 
N

Noah Roberts

Rolf said:
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.
 
N

Noah Roberts

Yannick said:
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?
 
T

Tony

blargg said:
Tony said:
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.


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
 
G

Gerhard Fiedler

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
 
G

Greg Herlihy

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


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
 
T

Tony

Yannick Tremblay said:
Yet some peoples get killed every years by car fume exhaust in enclosed
places...

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
 
T

Tony

blargg said:
Tony said:
blargg said:
Tony wrote:
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.

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.

Tony
 
T

Tony

blargg said:
Tony said:
blargg said:
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
 

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,057
Latest member
KetoBeezACVGummies

Latest Threads

Top