[comp.lang.c] When do you use const

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (02/02/91)

In article <1991Feb1.203935.18927@csrd.uiuc.edu> bliss@sp64.csrd.uiuc.edu (Brian Bliss) writes:
>  func f (const int *x, int *y);
>  then once the comipler fetches the value of *x, it need not fetch
>  it again in the subroutine, means it is constant.  if it were not
>  constant, then we could potentially modify the value of *x by 
>  assigning through *y (if x == y), and the compiler would need to
>  recalculate *x every time it was needed (if *y or any global variable
>  has been modified since the last calculation of *x).

Wait a minute. I thought const was only a prohibitive qualifier (you
can't set *x = foo) rather than an assertive qualifier (*x won't
change while it's in scope). Aren't you allowed to call f(&z,&z) upon an
int z (assuming prototypes are in scope), and doesn't f() have to reload
*x every time?

---Dan

paul@tredysvr.Tredydev.Unisys.COM (Paul Siu) (02/02/91)

In ANSI C, you can define a variable as constant by preceeding it with const.
You can for example define a double variable x that you cannot change by

     const double x;

However, what is the advantage of using const over #define?  Why was the
reason for its addition to ANSI C.

Paul Siu
paul@tredysvr.tredydev.unisys.com

bliss@sp64.csrd.uiuc.edu (Brian Bliss) (02/02/91)

In article <1220@tredysvr.Tredydev.Unisys.COM>,
paul@tredysvr.Tredydev.Unisys.COM (Paul Siu) writes:
|> In ANSI C, you can define a variable as constant by preceeding it
with const.
|> You can for example define a double variable x that you cannot change by
|> 
|>      const double x;
|> 
|> However, what is the advantage of using const over #define?  Why was the
|> reason for its addition to ANSI C.
|> 
|> Paul Siu
|> paul@tredysvr.tredydev.unisys.com


 because you can take the address of a variable declared as constant,
 but you can't take the address of a hard-coded constant.
 You can also declare

 const int *x;

 which means that the value to which x points will not be changed.
 therefore if you have:

 func f (const int *x, int *y);

 then once the comipler fetches the value of *x, it need not fetch
 it again in the subroutine, means it is constant.  if it were not
 constant, then we could potentially modify the value of *x by 
 assigning through *y (if x == y), and the compiler would need to
 recalculate *x every time it was needed (if *y or any global variable
 has been modified since the last calculation of *x).

 Not only that, but the type information for a symbol declared as
 const is included in the dbx symbol table information, and
 you can refer to that constant by name when debugging.

 What I welcome even more that the const declaration is the
 volatile declaration.  Anyone who does parallel programming
 has run into the bug at a syncronization point:

 while (x);

 which means "wait unitl another processor changes the value of x to nonzero".
 unfortunately, many compilers do not re-fetch the value of x from 
 memory each iteration of the loop (common subexpression elimination
 across loop iterations), and therefore go into an infinite loop.
 declaring x as volatile should tell the compiler that it's value can
 be changed without the current process doing so.

 bb

cc100aa@prism.gatech.EDU (Ray Spalding) (02/02/91)

In article <1220@tredysvr.Tredydev.Unisys.COM> paul@tredysvr.Tredydev.Unisys.COM (Paul Siu) writes:
>However, what is the advantage of using const over #define?  Why was the
>reason for its addition to ANSI C.

I believe "const" was added to (a) announce objects that may be placed
in read-only memory, (b) provide possible opportunities for
optimization, and (c) provide possible opportunities for diagnostics.
These would all seem to be possible with #defines of simple constants
like 3.14 or "abc" as well.  But with "const", you can have read-only
pointers, pointers to read-only objects, and read-only structs, arrays,
etc.  You can also take the address of a "const" variable (with &), but
not of a literal constant.

Of course, the "const" keyword is also used to denote that a function
will not alter an array argument; a different usage but one that can be
checked for optimizations and violations in a similar way by a
compiler.
-- 
Ray Spalding, Technical Services, Office of Information Technology
Georgia Institute of Technology, Atlanta Georgia, 30332-0715
uucp:     ...!{allegra,amd,hplabs,ut-ngp}!gatech!prism!cc100aa
Internet: cc100aa@prism.gatech.edu

kdq@demott.com (Kevin D. Quitt) (02/03/91)

In article <1220@tredysvr.Tredydev.Unisys.COM> paul@tredysvr.Tredydev.Unisys.COM (Paul Siu) writes:
>In ANSI C, you can define a variable as constant by preceeding it with const.
>You can for example define a double variable x that you cannot change by
>
>     const double x;
>
>However, what is the advantage of using const over #define?  Why was the
>reason for its addition to ANSI C.

    Your variable x above is pretty useless, since it has no initialized
value (and is therefore zero).  How about:

const char	*foo	= "some really long string";

    If this is #defined, and is accessed in several places, your
compiler may save multiple copies of the string.  Even if your compiler
is smart enough to make it a single instance, it won't do this over
several modules. 

  Another advantage is in the optimization phases, where the const keyword
provides more information to the optimizer.


-- 
 _
Kevin D. Quitt         demott!kdq   kdq@demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last

steve@taumet.com (Stephen Clamage) (02/05/91)

paul@tredysvr.Tredydev.Unisys.COM (Paul Siu) writes:

>However, what is the advantage of using const over #define?  Why was the
>reason for its addition to ANSI C.

A lot of good answers were posted to this question, but I didn't see any
mention of scoping.  Macros are not scoped.  They exist from the textual
point of declaration to the end of the compilation, unless #undef'd.  So
an innocent #define buried somewhere in the program (inside a function,
or in a nested include file) can unintentionally affect later code.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

greywolf@unisoft.UUCP (The Grey Wolf) (02/06/91)

In article <1991Feb2.181948.2147@demott.com> kdq@demott.com (Kevin D. Quitt) writes:
[ const double x; example deleted ]
>    Your variable x above is pretty useless, since it has no initialized
>value (and is therefore zero).  How about:
>
>const char	*foo	= "some really long string";
>
>    If this is #defined, and is accessed in several places, your
>compiler may save multiple copies of the string.  Even if your compiler
>is smart enough to make it a single instance, it won't do this over
>several modules. 

I know, I know, not ALL Unices are BSD, and not everyone can do this (yet),
but there is something called xstr on most sensible systems which solves the
#define problem quite nicely across multiple modules.

for module in modules
do	cc -E $module.c | xstr -
	cc -c x.c
	mv x.o module.o
	mv x.c module.cx 	# (if you want to see what it's doing)
done
cc -c xs.c
mv xs.o strings.o

>
>  Another advantage is in the optimization phases, where the const keyword
>provides more information to the optimizer.

This does not get solved by xstr :-)...

Where possible, the old method was to use cc -R on the resulting strings
object (xs.o) to make the strings shared/read-only[*].  The C shell is
compiled like this.  What with the advent of ANSI C, it appears that the
need for such a compiler flag has been obsoleted by the presence of the
"const" qualifier.

xstr still has its uses -- in places where quoted phrases might be used more
than once (such as {fprintf(stderr,"ioctl: "); perror(arg);} sequences)
all references to the quoted phrase would get changed to be pointers to
the master string array.

> 
> 
>-- 
> _ 
>Kevin D. Quitt demott!kdq kdq@demott.com 
>DeMott Electronics Co. 14707 Keswick St.  Van Nuys, CA 91405-1266 
>VOICE (818) 988-4975 FAX (818) 997-1190 MODEM (818) 997-4496 PEP last


-- 
thought:  I ain't so damb dumn!	| Your brand new kernel just dump core on you
war: Invalid argument		| And fsck can't find root inode 2
				| Don't worry -- be happy...
...!{ucbvax,acad,uunet,amdahl,pyramid}!unisoft!greywolf