begin  quoting Christopher Smith as of Sun, Oct 01, 2006 at 06:32:04PM -0700:
> Stewart Stremler wrote:
> > begin  quoting Christopher Smith as of Sun, Oct 01, 2006 at 03:22:49PM 
> > -0700:
> >   
> >> James G. Sack (jim) wrote:
> >>     
> >>> Stewart Stremler wrote:
> >>>       
> >>>> ..
> >>>> My problem with const almost always comes down to not using it
> >>>> consistently,
> >>>>         
> >> Hehe. Yeah, POSIX and Win32 interfaces were generally defined prior to
> >> widespread use of "const". To a large degree people have gone back and
> >> fixed these declarations, but there is nonetheless a lot of old code.
> >>     
> >
> > There's a break in habits required when shifting from old code to
> > new code as well.
> >   
> Fair enough. Easy solution: never work with old code. ;-)
> >> That said, so long as you really believe that a function will honor a
> >> "const" contract, there is little harm in casting away const when you
> >> call the function.
> >>     
> >
> > I work with people who would flag such a thing as a "major bug"... :-/
> >
> > (And I'm not sure I disagree. If the compiler complains, fix the code!)
> >   
> Doing the cast should keep the compiler from complaining. Typically
> where I see this is with old libraries/headers. Basically I just write a
> wrapper function that takes the variable as a const, casts it, and then
> calls the old function. If the function doesn't actually follow the
> contract, then you need to do a copy (and probably change the semantics
> of the interface).
> >>>> and then starting from the wrong side ("Oh, I think I'll make this a
> >>>> const. Whoops, that function doesn't take const, but now it needs
> >>>> to. Whoops, it passes that value on to a function that doesn't use 
> >>>> const either!").  And when one is done inserting "const" in all the 
> >>>> places
> >>>> that should have "const" in 'em.... the code has been uglified. Bleah.
> >>>>         
> >> Generally, I've found these scenarios tend to be pretty illuminating
> >> experiences actually, as they typically lead to discovering that the
> >> const contract isn't being held somewhere you thought it was.
> >>     
> >
> > Doesn't make it less painful or prettier, alas.
> >   
> Of course. Getting the contract wrong is going to be painful and ugly
> with or without const. At least with const the compiler can help catch
> the problem and steer you through to fixing it.
> >>> I personally, never felt too much urge to declare my (er..) variables as
> >>> const. Does that happen a lot?
> >>>   
> >>>       
> >> I guess it depends.  I find it useful to have const member variables. It
> >> also tends to be nicer to define constants using const instead of the
> >> evil #define. 
> >>     
> >
> > Heh.
> >
> > I only find #define evil if it actually *does* something;
> Just using it for constants "does" something. This is why you have to
> carefully avoid giving things names that might contain a substring for a
> macro.
> >>               For variables within a function,  const mostly helps with
> >> readibility, as someone who is reading the code for the first time and
> >> seeing some kind of problem towards the end of a function, they can see
> >> that it is declared const at the beginning and skip over most of the
> >> intervening code.
> >>     
> >
> > Unless, of course, the language being used magically un-consts a
> > const...
> >   
> Yeah, that would be bad.
> >> Note that one other aspect of const is that it makes the optimizer's job
> >> easier/possible, particularly during the compilation phase or if you are
> >> using dynamic linking/shared libraries.
> >>     
> >
> > Isn't that what volatile is for? "You can't optimize this access, but
> > everything else is fair game."  The compiler already has logic to
> > determine that a variable won't change in the scope of current
> > execution.
> >   
> Volatile means that a variable could be changed by something outside the
> current thread of control. const tells you that even the current thread
> won't modify it.

Yes. So a compiler cannot "optimize" a volatile variable, but everything
else is fair game.

>                  Some sample code probably makes it clear:
> 
> void foo_vol(volatile int* x);
> void foo_norm(int* x);
> void foo_const(const int* x);

(Is saving 2-5 characters *really* that significant?)

> volatile int vol = 1;
> int normal = 2;
> const int constant = 3;
> 
> foo_vol(&vol); //contents of vol may change before, during, and after
> execution of foo()
> foo_norm(&normal); //contents of normal may change during execution of foo()
> foo_const(&constant); //contents of constant will not change, period.
> 
> printf("%d:%d:%d\n", vol, normal, constant);
> 
> So, when the compiler sees foo_vol(&vol);, it basically has to assume
> the worst with regard to variable access. It pretty much will have to
> access main memory for each and every access to vol, including the
> printf.

Which as it should be.

>         When it sees foo_norm(&normal), it can do analysis to determine
> that normal isn't changed before or after calling the function, but it
> needs access to the definition of foo_norm() (which it often does not
> have) in order to be certain that it isn't modified *during* the call.

This depends on the language and the environment, and is an example of
where runtime optimization can beat compile-time optimization (thus, how
Java can beat out C and C++ for some real-world problems, despite the
howls of outrage and accusation of "lies and cheating" from that camp).

> Now, the linker might be able to figure this out, iff it is statically
> linking in foo_norm(), but if it's a shared library, no dice. With the
> case of foo_const(&constant), it doesn't need to worry about that. In
> fact it can safely just hard code in 3 for the printf line.

An optimizing linker?

I suppose it could be done. Probably has been.

But as our processors are getting more and more sophisticated, that
just seems like wasted work, if not actively harmful.  Let the runtime
do the optimization -- it *knows* what's actually going on.
 
> Interestingly, this kind of stuff becomes much more important once you
> are dealing with threads/memory barriers.

Yup.

Concurrent access adds all sorts of fun wrinkles, to the point where I
now believe that a language ought to have pre-emptive concurrent threads
as part of its design.

I have a big problem with all this effort being done for *performance*
reasons, before a profiler has even been run on the code. "We need feature
X to enable our performance optimizations!" is entirely the wrong
argument to make.  It's often wasted work (premature optimization) that
could presumably be better spent elsewhere.

The right argument for const (I really do want to smack someone upside
the head for choosing a truncated keyword) is _only_ for the "contract"
side of things.  When performance arguments enter into it, then the
appropriate response is to discard it, and wait for the profiler to
tell you where you need to concentrate your energy.

-- 
_ |\_
 \|

-- 
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg

Reply via email to