[comp.lang.c] Expressions in initializers

rabbieh@ajpo.sei.cmu.edu (Harold Rabbie) (03/04/91)

Here's one for the comp.lang.c.lawyers - K&R 2 says (without explanation)
that non-constant expressions can be used as initializers only for static 
scalars, not for automatics, and not for aggregates.

e.g. I can say:

static double x = sqrt( 2.0 );

but I can't say:

void foo( void ) 
{
    double x = sqrt( 2.0 );
}

nor can I say:

static struct foo {
    double x;
} bar = { sqrt( 2.0 ) };

What's the deal here - is ANSI easing up on those no-good implementers :-)
or is there a valid reason for this restriction?

P.S. No need to FAQ me over on this one.

torek@elf.ee.lbl.gov (Chris Torek) (03/04/91)

In article <760@ajpo.sei.cmu.edu> rabbieh@ajpo.sei.cmu.edu (Harold Rabbie)
writes:
>Here's one for the comp.lang.c.lawyers - K&R 2 says (without explanation)
>that non-constant expressions can be used as initializers only for static 
>scalars, not for automatics, and not for aggregates.

I think you have misread something here.  Initializers must be constants
*except* when:

	a) the variable being set is automatic, and
	b) the variable being set is not an aggregate.

>e.g.
>static double x = sqrt( 2.0 );

Illegal; x is not automatic.

>void foo( void ) { double x = sqrt( 2.0 ); }

Legal: x is automatic and not an aggregate (not a structure, union,
nor array).

>static struct foo {
>    double x;
>} bar = { sqrt( 2.0 ) };

Illegal; bar is not automatic.

The more interesting case is:

	void silly(void) { struct silly { double x; } bar = { sqrt(2.0) }; }

which is illegal, even though `bar' is automatic and `bar.x = sqrt(2.0);'
is legal.

>What's the deal here - is ANSI easing up on those no-good implementers :-)
>or is there a valid reason for this restriction?

Apparently the theory behind this particular example is that constant
aggregate initializers can be compiled into calls to memcpy():

	void silly(void) {
		struct silly { double x; } bar = { 3.142857142857143 };
	}

is in some sense equivalent to:

	void silly(void) {
		static struct silly { double x; } __L1 = { 3.142857142857143 };
		struct silly bar;
		memcpy((void *)&bar, (void *)&__L1, sizeof bar);
	}

and this is somehow considered to have some advantage over:

	void silly(void) {
		struct silly { double x; } bar;
		bar.x = 3.142857142857143;
	}
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

volpe@camelback.crd.ge.com (Christopher R Volpe) (03/04/91)

In article <760@ajpo.sei.cmu.edu>, rabbieh@ajpo.sei.cmu.edu (Harold
Rabbie) writes:
|>Here's one for the comp.lang.c.lawyers - K&R 2 says (without explanation)
|>that non-constant expressions can be used as initializers only for static 
|>scalars, not for automatics, and not for aggregates.

Read it again. You have it almost backwards.

|>
|>e.g. I can say:
|>
|>static double x = sqrt( 2.0 );

No you can't.

|>
|>but I can't say:
|>
|>void foo( void ) 
|>{
|>    double x = sqrt( 2.0 );
|>}

Yes you can.

|>
|>nor can I say:
|>
|>static struct foo {
|>    double x;
|>} bar = { sqrt( 2.0 ) };

That's correct.

|>
|>What's the deal here - is ANSI easing up on those no-good implementers :-)
|>or is there a valid reason for this restriction?
|>
|>P.S. No need to FAQ me over on this one.

Statics are initialized at compile time, therefore they can't be initialized
by an expression that can be evaluated only at runtime.
                         
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

mcdonald@aries.scs.uiuc.edu (Doug McDonald) (03/04/91)

In article <17270@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>In article <760@ajpo.sei.cmu.edu>, rabbieh@ajpo.sei.cmu.edu (Harold
>Rabbie) writes:
>|>Here's one for the comp.lang.c.lawyers - K&R 2 says (without explanation)
>|>that non-constant expressions can be used as initializers only for static 
>|>scalars, not for automatics, and not for aggregates.
>
>Read it again. You have it almost backwards.
>
>|>
>|>e.g. I can say:
>|>
>|>static double x = sqrt( 2.0 );
>
>No you can't.
>
>
>Statics are initialized at compile time, therefore they can't be initialized
>by an expression that can be evaluated only at runtime.
>                         


sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
some people don't want to write compilers that do that (i.e. they are too
lazy), but it most certainly CAN be evaluated.

Perhaps a different explanation is appropriate?

Doug McDonald

gwyn@smoke.brl.mil (Doug Gwyn) (03/05/91)

In article <760@ajpo.sei.cmu.edu> rabbieh@ajpo.sei.cmu.edu (Harold Rabbie) writes:
-Here's one for the comp.lang.c.lawyers - K&R 2 says (without explanation)
-that non-constant expressions can be used as initializers only for static 
-scalars, not for automatics, and not for aggregates.

That's not what MY copy of K&R2 says, nor is it what the C standard says.

volpe@camelback.crd.ge.com (Christopher R Volpe) (03/05/91)

In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu>,
mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
|>sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
|>some people don't want to write compilers that do that (i.e. they are too
|>lazy), but it most certainly CAN be evaluated.

"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
is an invocation of a function. How is the compiler supposed to know
what sqrt is? I could have in another file:

double sqrt(double x)
{
  return x - 1.0;
}
                              
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

torek@elf.ee.lbl.gov (Chris Torek) (03/05/91)

In article <17294@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com
(Christopher R Volpe) writes:
>"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
>is an invocation of a function. How is the compiler supposed to know
>what sqrt is? I could have in another file:
>
>double sqrt(double x)
>{
>  return x - 1.0;
>}

Not in ANSI C (at least, not if you `#include <math.h>'; I am not sure
about the case where you do not include the standard header).  Compilers
can of course define their own languages and allow

	static double root2 = sqrt(2.0);

but someone writing ANSI C should assume neither this nor that writing

	double sqrt(double x) { return x - 1.0; }

will work.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

dave@cs.arizona.edu (Dave P. Schaumann) (03/05/91)

In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
>some people don't want to write compilers that do that (i.e. they are too
>lazy), but it most certainly CAN be evaluated.
>
>Perhaps a different explanation is appropriate?

You want to link the whole floating point library to the C compiler?

First thing you need to realize is that there is no special, pre-defined
function sqrt() in C.  (Suprise!!!)  The function sqrt lives in a link
libarary.  As far as the C compiler knows, it's just another user-defined
function.  So it can't really be evaluated at compile time.

That said, sqrt() (or any other linked-in or user defined function) is known
at run-time, so you could have static int foo = bar(baz) ; be short-hand for
an initialization that gets done before main() is called.  This is another
kettle of fish entirely, though.

-- 
		Dave Schaumann		dave@cs.arizona.edu
'Dog Gang'!  Where do they get off calling us the 'Dog Gang'?  I'm beginning to
think the party's over.  I'm beginning to think maybe we don't need a dog.  Or
maybe we need a *new* dog.  Or maybe we need a *cat*! - Amazing Stories

ds@juniper09.cray.com (David Sielaff) (03/05/91)

In article <10592@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes:
>In article <17294@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com
>(Christopher R Volpe) writes:
>>"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
>>is an invocation of a function. How is the compiler supposed to know
>>what sqrt is? I could have in another file:
>>
>>double sqrt(double x)
>>{
>>  return x - 1.0;
>>}
>
>Not in ANSI C (at least, not if you `#include <math.h>'; I am not sure
>about the case where you do not include the standard header).  Compilers
>can of course define their own languages and allow
>
>	static double root2 = sqrt(2.0);
>
>but someone writing ANSI C should assume neither this nor that writing
>
>	double sqrt(double x) { return x - 1.0; }
>
>will work.
>-- 
>In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
>Berkeley, CA		Domain:	torek@ee.lbl.gov

According to ANSI C, it is not necessary to `#include <math.h>' to have
this effect.  Identifiers such as `sqrt' are always reserved as
identifiers with external linkage.  Thus you could define a new `sqrt'
as a static function in a compilation unit, but if `sqrt' ends up with
external linkage, the compiler can assume that it means the library
function.

Dave Sielaff
Cray Research

ckp@grebyn.com (Checkpoint Technologies) (03/05/91)

In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
>some people don't want to write compilers that do that (i.e. they are too
>lazy), but it most certainly CAN be evaluated.

You are assuming that the compiler knows what the function sqrt(double)
does.  I think I've heard of a few that do.  Most don't.
-- 
First comes the logo: C H E C K P O I N T  T E C H N O L O G I E S      / /  
                                                                    \\ / /    
Then, the disclaimer:  All expressed opinions are, indeed, opinions. \  / o
Now for the witty part:    I'm pink, therefore, I'm spam!             \/

volpe@camelback.crd.ge.com (Christopher R Volpe) (03/05/91)

In article <17294@crdgw1.crd.ge.com>, I wrote
|>
|>"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
|>is an invocation of a function. How is the compiler supposed to know
|>what sqrt is? I could have in another file:
|>
|>double sqrt(double x)
|>{
|>  return x - 1.0;
|>}

It was pointed out to me that this is illegal.                   
==================
Chris Volpe
G.E. Corporate R&D
volpecr@crd.ge.com

henry@zoo.toronto.edu (Henry Spencer) (03/06/91)

In article <17294@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
>is an invocation of a function. How is the compiler supposed to know
>what sqrt is?

If <math.h> has been included, an ANSI C compiler may well have been
informed, by magic in it, that sqrt means "square root".

>I could have in another file:
>double sqrt(double x)
>{

Naughty, naughty.  The external identifiers in the ANSI C library, including
sqrt, are reserved; you redefine them at your peril.
-- 
"But this *is* the simplified version   | Henry Spencer @ U of Toronto Zoology
for the general public."     -S. Harris |  henry@zoo.toronto.edu  utzoo!henry

lerman@stpstn.UUCP (Ken Lerman) (03/06/91)

In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>
>sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
>some people don't want to write compilers that do that (i.e. they are too
>lazy), but it most certainly CAN be evaluated.
>
>Perhaps a different explanation is appropriate?
>
>Doug McDonald

It may be true that under ANSI C sqrt(2.0) CAN be evaluated at compile
time.  But prior to ANSI, the value of sqrt(2.0) could not be because
the programmer was free to call any function he wanted "sqrt".  Prior
to ANSI, the semantics of sqrt might not be determined until link
time.

Ken

rjc@uk.ac.ed.cstr (Richard Caley) (03/06/91)

In article <1991Mar5.042141.21825@grebyn.com>, Checkpoint Technologies (ct) writes:

In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:

dmd> sqrt(2.0) is an expression. It CAN be evaluated at compile time.
dmd> Perhaps some people don't want to write compilers that do that
dmd> (i.e.  they are too lazy), but it most certainly CAN be
dmd> evaluated.

ct> You are assuming that the compiler knows what the function sqrt(double)
ct> does.  I think I've heard of a few that do.  Most don't.

Is it possible to know before the program is linked (run if you have
run time linking!). What stops me from defining my own sqrt?

--
rjc@cstr.ed.ac.uk	

browns@iccgcc.decnet.ab.com (Stan Brown) (03/06/91)

In article <1032@caslon.cs.arizona.edu>, dave@cs.arizona.edu (Dave P. Schaumann) writes:
> First thing you need to realize is that there is no special, pre-defined
> function sqrt() in C.  (Suprise!!!)  The function sqrt lives in a link
> libarary.  As far as the C compiler knows, it's just another user-defined
> function.  So it can't really be evaluated at compile time.

This was my thought at first, and it's certainly true for non-ANSI compilers.

But App. F.2 of the ANSI standard says undefined behavior results "if the 
program redefines a reserved external identifier (4.1.2)."

Sec 4.1.2.1 says: "... All identifiers with external linkage in any of
the following sections (including the future library directions) are
always reserved for use as identifiers with external linkage. ... If a
program declares or defines an identifier with the same name as an
identifier reserved in that context (other than as allowed by 4.1.6),
the behavior is undefined."

Sec 4.1.6 is a page and a half long, but all the referenced 'exceptions'
have to do with declaring library functions, not with custom function
definitions created by the user.

Sec 4.5 is about <math.h>.  Sec 4.5.5.2 describes the sqrt function.

So 'sqrt' is a reserved identifier with external linkage, and behavior
is undefined if the user redefined the 'sqrt' identifier by providing
her own sqqrt function.

So a conforming compiler is free to consider sqrt(2.0) to be a
compile-time constant.

Having said all that, I think the way the undefined behavior _should_
work is the way Dave suggests.  And I'd expect it to work that way on
any real-life implementation, even though the Standard says we can't
rely on it.

My opinions are mine:  I don't speak for any other person or company.
                   email (until 91/4/30): browns@iccgcc.decnet.ab.com
Stan Brown, Oak Road Systems, Cleveland, Ohio, USA    +1 216 371 0043

dave@cs.arizona.edu (Dave P. Schaumann) (03/06/91)

In article <3599.27d3ca8a@iccgcc.decnet.ab.com> browns@iccgcc.decnet.ab.com (Stan Brown) writes:
|In article <1032@caslon.cs.arizona.edu>, dave@cs.arizona.edu (Dave P. Schaumann) writes:
|| First thing you need to realize is that there is no special, pre-defined
|| function sqrt() in C.  [more embarassing comments deleted :-/ ]

|This was my thought at first, and it's certainly true for non-ANSI compilers.
|
|But App. F.2 of the ANSI standard says undefined behavior results "if the 
|program redefines a reserved external identifier (4.1.2)."
|[...]
|So 'sqrt' is a reserved identifier with external linkage, and behavior
|is undefined if the user redefined the 'sqrt' identifier by providing
|her own sqqrt function.

Ok, ok, OK!!!  I was wrong.  I know it now.  I spoke from experience with
the pre-standard C.  I guess I really need to take a close look at K&R2 to
see what other suprises are lurking for me there...

That aside, the logical conclusion of "constant" evaluation at compile-time
will make C compiler into a C interpreter as well.  I have been reminded in
the past that C is supposed to be a small language (when wishing for a
largest-of operator on enums).  Think how much more work the compiler must
do to evaluate constant-parameter functions at compile time, even if you
limited this to standard library functions.

Can you say "creeping featurism?"  Can you say "kitchen sink?"
Sure!  I knew you could...

-- 
		Dave Schaumann		dave@cs.arizona.edu
'Dog Gang'!  Where do they get off calling us the 'Dog Gang'?  I'm beginning to
think the party's over.  I'm beginning to think maybe we don't need a dog.  Or
maybe we need a *new* dog.  Or maybe we need a *cat*! - Amazing Stories

suhonen@kunto.jyu.fi (Timo Suhonen) (03/07/91)

rjc@uk.ac.ed.cstr (Richard Caley) writes:

   ct> You are assuming that the compiler knows what the function sqrt(double)
   ct> does.  I think I've heard of a few that do.  Most don't.

   Is it possible to know before the program is linked (run if you have
   run time linking!). What stops me from defining my own sqrt?

Doesn't ANSI standard let the compiler know the standard functions???
If so, then sqrt(double) can be evaluated at compile time. And I
think that is just what every compiler SHOUD do!
--
Timo Suhonen        I am logged in, therefore I am        suhonen@nic.funet.fi
                                                          suhonen@kunto.jyu.fi
   Opinions(?) are mine (if not stolen), NOT those of Univ. of Jyvaskyla.

ddh@hare.cdc.com (Dan Horsfall) (03/08/91)

In article <1043@caslon.cs.arizona.edu>
  dave@cs.arizona.edu (Dave P. Schaumann) writes:
> 
>         ... the logical conclusion of "constant" evaluation at compile-time
> will make C compiler into a C interpreter as well.  I have been reminded in
> the past that C is supposed to be a small language (when wishing for a
> largest-of operator on enums).  Think how much more work the compiler must
> do to evaluate constant-parameter functions at compile time, even if you
> limited this to standard library functions.
> 
> 		Dave Schaumann		dave@cs.arizona.edu

OK, heres my $0.02.  How many of you out there really want "constant 
expressions" evaluated over and over again at run-time??  How many
times will your code be run, vs. how many times will be it be 
compiled? 

I know I'll attract flames galore with this attitude, but I expect, even
assume decent compilers to eliminate this stuff without being told (i.e.,
without the higher optimization levels).  In this shop, the goal is
NOT performance for the developer -- it's meeting the needs of the
fur-bearing, revenue-producing, end user -- the Customer!

I admit, of course, that not every one needs to write code as if his
livlihood depended on it.

-- 
   Horse
                                       +    Control Data Corporation      
   Dan Horsfall     +1-612-482-4622    +    4201 Lexington Ave North      
   Internet   ddh@dash.udev.cdc.com    +    Arden Hills MN 55126 USA      

dave@cs.arizona.edu (Dave P. Schaumann) (03/08/91)

In article <31134@shamash.cdc.com> ddh@dash.udev.cdc.com (Dan Horsfall) writes:
>OK, heres my $0.02.  How many of you out there really want "constant 
>expressions" evaluated over and over again at run-time??  How many
>times will your code be run, vs. how many times will be it be 
>compiled? 

I think that this is a valid question for anyone who thinks about programming
languages, and how to make them more useful, and not just to those producing
code to be sold.

The root question here is really "how much work should the compiler do to
optimize your program?"  Now, constant evaluation is an obvious thing to
do at compile time.  It has the advantage that you can use constant expressions
wherever you can use a constant.  The disadvantage of this is that to do
this, you have to have an expression interpreter inside the compiler.

Now, for "hardware-defined" operations like + - * / etc, you essentially
get expression evaluation for free when you do expression parsing.  The
trouble starts when you want to do something non-trivial (square-root being
the motivating example).

Now, if your machine has a built-in square-root operation, this is still not
too bad.  But consider the more general case.  We would really want to be able
to use *any* function available in the standard library.  That means that the
full standard library must be available for execution at compile time.  It
should be clear that this is going to make your compiler *a lot* bigger.

But how useful is it to be able to call any standard function at compile
time?  In some cases, it could be very useful.  If you have a large, constant
table with values dependent on functions in the standard library, clearly
this is a big win.  However, in my experience, this is a rather exceptional
occurrance, and the expanded compiler is a big lose to anyone who doesn't
need/use/want this feature.

Also, I should mention that there are some obvious work-arounds (although
none as attractive as compile-time evaluation) to this problem:
	- evaluation at start of run-time (could be slow)
	- using a pre-compiler to evaluate constants (increases the complexity
	  of the source, and introduces precision loss due to 
	  internal/external conversion (if your using float/doubles))

As an aside, does anyone know if Fortran (being the canonical number-crunching
language) allows this sort of thing?

-- 
Dave Schaumann | dave@cs.arizona.edu | Short .sig's rule!

mcdonald@aries.scs.uiuc.edu (Doug McDonald) (03/08/91)

In article <1075@caslon.cs.arizona.edu> dave@cs.arizona.edu (Dave P. Schaumann) writes:
>Now, if your machine has a built-in square-root operation, this is still not
>too bad.  But consider the more general case.  We would really want to be able
>to use *any* function available in the standard library.  That means that the
>full standard library must be available for execution at compile time.  It
>should be clear that this is going to make your compiler *a lot* bigger.
>


A testable assumption. On my computer I have three C compilers,
which range in size from 440 kilobytes to 800 kilobytes. Each one comes
with several different floating point libraries, for use with one
of several floating point units (or none at all) and these have sizes
varying from 30 to 45 kilobytes. Some of the compilers have the
libraries already linked in.


So it will NOT make a real modern compiler that much bigger. It might
have an effect if you use the old piece of crap sometimes delivered with certain
operating systems. 


Doug McDonald

hansm@cs.kun.nl (Hans Mulder) (03/08/91)

In article <3599.27d3ca8a@iccgcc.decnet.ab.com> browns@iccgcc.decnet.ab.com (Stan Brown) writes:
>So a conforming compiler is free to consider sqrt(2.0) to be a
>compile-time constant.

Nope.  The ANSI standard gives an exhaustive list of operators that
can appear in a "constant expression" as required in an aggregate
initialiser and function calls are not on the list.

Consequently,

	struct silly { double d; } foo = { sqrt(2.0) };

is illegal.  This has nothing to do with the question of whether the
optimiser is allowed to replace

	foo.d = sqrt(2.0);
by
	foo.d = 1.4142135623730950488;


Also missing from the list is the array subscript operator, thus

	struct silly { char ch; } foo = { "hello"[3] };

is illegal, the fact that "hello"[3] == 'l' notwithstanding.


Have a nice day,

Hans Mulder	hansm@cs.kun.nl

steve@taumet.com (Stephen Clamage) (03/08/91)

suhonen@kunto.jyu.fi (Timo Suhonen) writes:

>rjc@uk.ac.ed.cstr (Richard Caley) writes:

>   ct> You are assuming that the compiler knows what the function sqrt(double)
>   ct> does.  I think I've heard of a few that do.  Most don't.

>   Is it possible to know before the program is linked (run if you have
>   run time linking!). What stops me from defining my own sqrt?

>Doesn't ANSI standard let the compiler know the standard functions???
>If so, then sqrt(double) can be evaluated at compile time. And I
>think that is just what every compiler SHOUD do!

In Standard (ANSI/IOS) C, 'sqrt' is reserved for use as an external
identifier, and reserved for use as a file-level identifier if <math.h>
is included.  So consider the following C file (<math.h> NOT included):

	static double sqrt(double d) { return d / 2.0; }
	double x = sqrt(2.0);
	... and more stuff ...

If this were allowed and the compiler were to initialize x to 1.414...
it would be wrong to do so.  The correct initial value for x would be 1.0.

If <math.h> is included, the above is illegal, and the only interpretation
for sqrt() is the one in <math.h>.  So the compiler could evaluate
library functions with constant arguments when the appropriate headers
were included.  This starts getting a bit complicated, such as
	double x = sqrt((double)(srand(strlen("Hello")),rand()));
which could be evaluated at compile time if <math.h>, <stdlib.h>, and
<string.h> were all included.  No, wait, srand() should affect the
runtime environment, so we shouldn't evaluate this one at compile time.
Golly, it IS getting complicated.

Now consider cross-compilers.  We would have to execute library functions
for the target system on the host, using target system arithmetic, which
may have data type sizes and formats different from the host.

In the end, what have we saved by all this complication?  It seems unlikely
that initializing static variables is a large part of the execution time,
or that significant extra code space would be taken up.  If you have a
loop like
	while(...) { ...  x += sin(2.5); ...  }
you can save execution time by rewriting it as
	double sin25 = sin(2.5);
	while(...) { ...  x += sin25; ...  }
(This may give less accurate results on systems, but there are no
guarantees either way.)

You do lose notational convenience by not being able to say
	double sqrt2 = sqrt(2.0);
at the file level.  C++ does allow this notation, but it evaluates the
function calls at run time, conceptually before main() begins execution.
Thus, with my first example, the static version of sqrt() get called,
and with a less perverse program, the library sqrt() gets called.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

henry@zoo.toronto.edu (Henry Spencer) (03/09/91)

In article <2842@wn1.sci.kun.nl> hansm@cs.kun.nl (Hans Mulder) writes:
>>So a conforming compiler is free to consider sqrt(2.0) to be a
>>compile-time constant.
>
>Nope.  The ANSI standard gives an exhaustive list of operators that
>can appear in a "constant expression" as required in an aggregate
>initialiser and function calls are not on the list.

Nope. :-)  3.4:  "An implementation may accept other forms of constant
expressions."  It is legitimate for an implementation to take that as
a constant expression, although the usage is not portable.

Incidentally, where did you find the "exhaustive list"?  K&R used to give
such a list (which had at least one error in it!), but the definition of
constant expressions in X3.159-1989 section 3.4 doesn't do it that way.
-- 
"But this *is* the simplified version   | Henry Spencer @ U of Toronto Zoology
for the general public."     -S. Harris |  henry@zoo.toronto.edu  utzoo!henry

rjc@uk.ac.ed.cstr (Richard Caley) (03/10/91)

In article <SUHONEN.91Mar7104347@kunto.jyu.fi>, Timo Suhonen (ts) writes:

rjc@uk.ac.ed.cstr (Richard Caley) writes:

rjc> Is it possible to know before the program is linked (run if you have
rjc> run time linking!). What stops me from defining my own sqrt?

ts> Doesn't ANSI standard let the compiler know the standard functions???
ts> If so, then sqrt(double) can be evaluated at compile time. And I
ts> think that is just what every compiler SHOUD do!

Thank's to everyone who let me know this. I hadn't realised it, not
having the stamina to read the standard.

On the other hand, not all the world is ANSI, and even if it were this
does not imply that you can (easily) do run time evaluation.

Gratuitous moan: While I understand the reasons for this restriction,
	it _is_ ugly as sin and does mean you need to have a linker
	which understands C.

--
rjc@cstr.ed.ac.uk

sbs@ciara.Frame.COM (Steven Sargent) (03/10/91)

If my compiler folds
	sqrt(2.0)
correctly, it knows the floating point rounding mode in my runtime
environment.  Seems like a bit much to ask.

-- 
Steven Sargent sbs@frame.com	"Frame's phone bill, my opinions."

gwyn@smoke.brl.mil (Doug Gwyn) (03/11/91)

In article <17294@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes:
>"The square root of two" can be evaluated at compile time, but "sqrt(2.0)"
>is an invocation of a function. How is the compiler supposed to know
>what sqrt is?

In a conforming hosted implementation, the external identifier "sqrt" is
reserved for the standard sqrt() function, and an implementation is
entitled to exploit that fact to, for example, substitute in-line code
that accesses floating-point hardware directly, rather than actually
perform a full C function call.

peter@ficc.ferranti.com (Peter da Silva) (03/13/91)

ts> Doesn't ANSI standard let the compiler know the standard functions???

Yes, but it doesn't require it to.
-- 
Peter da Silva.  `-_-'  peter@ferranti.com
+1 713 274 5180.  'U`  "Have you hugged your wolf today?"

philbo@dhw68k.cts.com (Phil Lindsay) (03/13/91)

In article <1032@caslon.cs.arizona.edu> dave@cs.arizona.edu (Dave P. Schaumann) writes:
>In article <1991Mar4.144939.8311@ux1.cso.uiuc.edu> mcdonald@aries.scs.uiuc.edu (Doug McDonald) writes:
>>sqrt(2.0) is an expression. It CAN be evaluated at compile time. Perhaps
>>some people don't want to write compilers that do that (i.e. they are too
>>lazy), but it most certainly CAN be evaluated.
>>
>>Perhaps a different explanation is appropriate?
>
>You want to link the whole floating point library to the C compiler?
>
>First thing you need to realize is that there is no special, pre-defined
>function sqrt() in C.  (Suprise!!!)  The function sqrt lives in a link
>libarary.  As far as the C compiler knows, it's just another user-defined
>function.  So it can't really be evaluated at compile time.
>
The MSC compiler "knows" strcpy(), memcpy(), etc... The compiler produces
inline versions of these functions. Compile guru's will do almost anything
for speed.

-- 
Phil Lindsay - "Patents threaten future technology"
Internet: philbo@dhw68k.cts.com  Phone: Wrk7143852311 Hm7142891201
UUCP:     {spsd,zardox,felix}!dhw68k!philbo
USMAIL: 152A S. Cross Creek Rd, Orange, Ca. 92669