[comp.lang.c] Use of Const keyword in ANSI C

cramer@optilink.UUCP (Clayton Cramer) (09/08/88)

I'm starting to use the 'const' keyword with the Microsoft V5.1 C compiler.
I've found something that may be a bug, or it may be that I don't 
adequately understand 'const'.

I've defined a structure:

    typedef struct Tag
        {
        const int       A;
        short           B;
        const char*     C;
        } TestType;

    TestType        Test1 = {10, 10, "test case"};

    Test1.A = 5;            /* compiler complains about this -- good */
    Test1.B = 20;           /* compiler accepts this -- fine */
    Test1.C = "not a test case";    /* compiler accepts this -- bad */

Should the attempt to set Test1.C to point to another string cause a
complaint from the compiler?

If I redefine the structure the same as above but with:

    const char          C[20];

and a statement:

    Test1.C[0] = '0';

the compiler complains (correctly) "lval specifies 'const' object".

So have I missed something here in my understanding of 'const', or
is the Microsoft compiler broke?

Clayton E. Cramer
..!hplabs!pyramid!kontron!optilin!cramer

gwyn@smoke.ARPA (Doug Gwyn ) (09/08/88)

In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
>    typedef struct Tag
>        {
>        const char*     C;
>        } TestType;
>    Test1.C = "not a test case";    /* compiler accepts this -- bad */

That's okay.  You've declared the C member to point to const chars,
and set it to point to a string literal.  If you want the POINTER to
be const, instead of what it points to, try
	char const *	C;

"const" is a type qualifer, not a storage class, so its relative
position within the type specifiers matters.

ok@quintus.uucp (Richard A. O'Keefe) (09/08/88)

In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
>I'm starting to use the 'const' keyword with the Microsoft V5.1 C compiler.
>I've found something that may be a bug, or it may be that I don't 
>adequately understand 'const'.
>I've defined a structure:
>    typedef struct Tag { ... const char* C; } TestType;
>    TestType Test1 = ...;
>    Test1.C = "not a test case";    /* compiler accepts this -- bad */

The compiler is right: const char *C is to be read *backwards*:
C is a pointer to readonly characters.  If you want C to be constant, say
	char * const C;		/* C is a constant pointer to char */
If you want *both* C and what it points to to be readonly, say
	const char * const C;

The "cdecl" utility -- available from comp.sources archives -- is a big help!

davidsen@steinmetz.ge.com (William E. Davidsen Jr) (09/09/88)

In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:

| I've defined a structure:
| 
|     typedef struct Tag
|         {
|         const int       A;
|         short           B;
|         const char*     C;
|         } TestType;
| 
|     TestType        Test1 = {10, 10, "test case"};
| 
|     Test1.A = 5;            /* compiler complains about this -- good */
|     Test1.B = 20;           /* compiler accepts this -- fine */
|     Test1.C = "not a test case";    /* compiler accepts this -- bad */

  I think it's right. You have a "pointer to const char" (I think) and a
quoted string is (can be?) a const string, so it works. After the first
assignment try
	Test1.C[2] = 'x';
and see if it tells you you can't modify a const string.
-- 
	bill davidsen		(wedu@ge-crd.arpa)
  {uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

chris@mimsy.UUCP (Chris Torek) (09/09/88)

In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
[structure containing]
>        const char*     C;
>
>    Test1.C = "not a test case";    /* compiler accepts this -- bad */
>
>Should the attempt to set Test1.C to point to another string cause a
>complaint from the compiler? ... [or] have I missed something here in
>my understanding of 'const' ... ?

The latter: `const' applies here to the characters, not to the pointer.
So `Test1.C[n] = expr' is illegal, but `Test1.C = expr' is legal.  If
you just want the pointer to be constant, use

	char *const C;

and if you want both constant, use

	const char *const C;

The `volatile' modifier works in the same fashion.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

curtw@hpcllca.HP.COM (Curt Wohlgemuth) (09/09/88)

Clayton Cramer says:

> I'm starting to use the 'const' keyword with the Microsoft V5.1 C compiler.
> I've found something that may be a bug, or it may be that I don't 
> adequately understand 'const'.
> 
> I've defined a structure:
> 
>     typedef struct Tag
>         {
>         const int       A;
>         short           B;
>         const char*     C;
>         } TestType;
> 
>     TestType        Test1 = {10, 10, "test case"};
> 
>     Test1.A = 5;            /* compiler complains about this -- good */
>     Test1.B = 20;           /* compiler accepts this -- fine */
>     Test1.C = "not a test case";    /* compiler accepts this -- bad */
> 
> Should the attempt to set Test1.C to point to another string cause a
> complaint from the compiler?

According to my reading of the ANSI Draft Standard, the delcaration
                      const char *C;
means that C is a pointer to a char object that must be guaranteed to
be constant.  In his scenario,
		      Test1.C = "not a test case";
certainly does not violate this:  the value located at the address that 
holds the string "test case" has not changed.  It still contains the
string "test case", but Test1.C just doesn't refer to it.

In order to prevent the field C to point elsewhere, I think he ought to
declare it as:
		      char * const C;

The ANSI Draft Standard says:
"const int * means (variable) pointer to constant int, and 
int * const means constant pointer to (variable) int."

If he wants a constant pointer, the second form should hold.

henry@utzoo.uucp (Henry Spencer) (09/09/88)

In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
>        const char*     C;
>    Test1.C = "not a test case";    /* compiler accepts this -- bad */
>
>Should the attempt to set Test1.C to point to another string cause a
>complaint from the compiler?

No.  You have misunderstood the (messy) syntax of const.  "const char *"
is a pointer to const char, not a const pointer to char.  To get a const
pointer to char, say "char *const C;" instead.  Yes, this is ugly.
-- 
Intel CPUs are not defective,  |     Henry Spencer at U of Toronto Zoology
they just act that way.        | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

scjones@sdrc.UUCP (Larry Jones) (09/10/88)

In article <441@optilink.UUCP>, cramer@optilink.UUCP (Clayton Cramer) writes:
> [assignment to a "const char *" works without complaint]
>
> So have I missed something here in my understanding of 'const', or
> is the Microsoft compiler broke?

You've missed the binding order - "const char *" is a pointer to a constant
character, what you want is "char * const" which is a constant pointer to
a (non-constant) character.

----
Larry Jones                         UUCP: uunet!sdrc!scjones
SDRC                                      scjones@sdrc.uucp
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150                  AT&T: (513) 576-2070
"Save the Quayles" - Mark Russell

marc@metavax.UUCP (Marc Paige) (09/14/88)

In article <8454@smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>In article <441@optilink.UUCP> cramer@optilink.UUCP (Clayton Cramer) writes:
>>    typedef struct Tag
>>        {
>>        const char*     C;
>>        } TestType;
>>    Test1.C = "not a test case";    /* compiler accepts this -- bad */
>
>That's okay.  You've declared the C member to point to const chars,
>and set it to point to a string literal.  If you want the POINTER to
>be const, instead of what it points to, try
>	char const *	C;
>
>"const" is a type qualifer, not a storage class, so its relative
>position within the type specifiers matters.

The second declaration is also wrong!!  char const and const char are
equivilent.  The way to declare a const pointer is:

	 char * const C;

This declares member C to be a const pointer to char.  You are correct in
your last statement though, const is a qualifier.


------------------------------------------------------------------------
"tired and shagged out from a prolonged squawk" - mpfc the parrot sketch

gwyn@smoke.ARPA (Doug Gwyn ) (09/15/88)

In article <3612@metavax.UUCP> marc@metavax.UUCP (Marc Paige) writes:
>	 char * const C;

Yes, I had misremembered the syntax.  Sorry.