[comp.lang.c] char *Foo VS. char Bar

bobmon@iuvax.cs.indiana.edu (RAMontante) (04/14/89)

A student turned up a curious problem today; before I tell the class what I
think the problem was I'd like some confirmation from the gurus here (or
denial, if you must :-( )

The essence of his code was

	char *foo = "     ";
	...
	sprintf(foo,"xxxx");

Using gcc on a VAX8650/Ultrix, the sprintf causes a bus error.  The standard
cc compiler produced code that "worked".  I had him change the declaration to

	char foo[6] = "     ";		/* assume I got the lengths correct */

and the program ran correctly as compiled by gcc.

My interpretation is that, in the original case, gcc has created a
(variable) pointer which is initialized to some *constant* storage which
can't be written to; cc doesn't make any writeable/read-only distinctions.
The second form created a (constant?) pointer to some storage that is
explicitly writeable, and happens to be filled with blanks initially.

(BTW:  He says that the original form worked under MSC under MSDOS, so I
infer that MSDOS/80x86 systems also don't enforce constant strings.)

All comments will be appreciated.  Thanx,
	Bob
--
Those who do not understand MSDOS are  | Bob Montante (bobmon@cs.indiana.edu)
condemned to write glowingly of it in  | Computer Science Department
slick, short-lived magazines.          | Indiana University, Bloomington IN

henry@utzoo.uucp (Henry Spencer) (04/14/89)

In article <19636@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>	char *foo = "     ";
>	...
>	sprintf(foo,"xxxx");
>
>Using gcc on a VAX8650/Ultrix, the sprintf causes a bus error.  The standard
>cc compiler produced code that "worked"...

Old C guaranteed that string constants were writeable storage.  ANSI C says
that the compiler is entitled to make them read-only if it wants.  Many
people have felt all along that writing into string constants was bad
practice.
-- 
Welcome to Mars!  Your         |     Henry Spencer at U of Toronto Zoology
passport and visa, comrade?    | uunet!attcan!utzoo!henry henry@zoo.toronto.edu

kremer@cs.odu.edu (Lloyd Kremer) (04/14/89)

In article <19636@iuvax.cs.indiana.edu> bobmon@iuvax.cs.indiana.edu (RAMontante) writes:
>A student turned up a curious problem today
>The essence of his code was
>
>	char *foo = "     ";
>	...
>	sprintf(foo,"xxxx");
>
>I had him change the declaration to
>
>	char foo[6] = "     ";		/* assume I got the lengths correct */


In the first case, foo is a character pointer, initially set to point at a
string literal.  In the secon case, foo is an array of 6 chars, whose contents
are initialized to 5 spaces followed by a '\0'.

Note that the second case constitutes aggregate initialization, and hence
requires that foo be of a global or static storage class.  The statement
is syntactically equivalent to

	int foo[6] = { 1, 2, 3, 4, 5, 0 };

In the second case, the contents of the array are always writeable.  The
question of whether the object to which foo points is writeable in the first
case is the question, "Are string literals writeable?"  Some compilers
insist that they are, taking pains to place string literals in data space
rather than constant space to accommodate it.  Other compilers insist that
they are not, and place them in protected space to enforce it.


					Lloyd Kremer
					Brooks Financial Systems
					{uunet,sun,...}!xanth!brooks!lloyd

austing@Apple.COM (Glenn L. Austin) (04/14/89)

>        char *foo = "     ";
>        ...
>        sprintf(foo,"xxxx");
>
>Using gcc on a VAX8650/Ultrix, the sprintf causes a bus error.  The standard
>cc compiler produced code that "worked".  I had him change the declaration to
>
>        char foo[6] = "     ";          /* assume I got the lengths correct */
>
>and the program ran correctly as compiled by gcc.
>
>My interpretation is that, in the original case, gcc has created a
>(variable) pointer which is initialized to some *constant* storage which
>can't be written to; cc doesn't make any writeable/read-only distinctions.
>The second form created a (constant?) pointer to some storage that is
>explicitly writeable, and happens to be filled with blanks initially.
>
>(BTW:  He says that the original form worked under MSC under MSDOS, so I
>infer that MSDOS/80x86 systems also don't enforce constant strings.)

I have found that this is a common problem.  You are correct in your assumption
that in the first case a pointer was created that pointed to a constant
declaration, and in the second case, space was allocated on the stack for an
array of characters that gets "preset" to spaces.  The fact that MSC under
MSDOS misses this shows how limited the OS is.  Under protected mode, depending
on the compiler (I haven't used MSC under OS/2 yet), you should also get a
bus error.

Incidentally, a Mac program written in MPW C 3.0 will also halt with a
bus error on this code.


-----------------------------------------------------------------------------
| Glenn L. Austin             | The nice thing about standards is that      | 
| Apple Computer, Inc.        | there are so many of them to choose from.   | 
| Internet: austing@apple.com |       -Andrew S. Tanenbaum                  |
-----------------------------------------------------------------------------
| All opinions stated above are mine -- who else would want them?           |
-----------------------------------------------------------------------------

arrom@aplcen.apl.jhu.edu (Ken Arromdee) (04/15/89)

Modifying a string literal is legal in pre-ANSI versions of C and not
necessarily so in ANSI versions.  Thus, neither MSC nor gcc was wrong.

Source: K&RII, page 194.

char *foo="   " is a pointer to a string literal. char bar[size]="   " is an
array, which gets initialized to the requested contents. 
--
               EARTH          |       --Kenneth Arromdee
           smog  |   bricks   |      UUCP: ....!jhunix!ins_akaa
        AIR     mud       FIRE|  INTERNET: arromdee@crabcake.cs.jhu.edu
      soda water |   tequila  |    BITNET: g49i0188@jhuvm
               WATER          |(please, no mail to arrom@aplcen)
Element chart from "Science Made Stupid".  (The chart seems rather popular...)

karl@haddock.ima.isc.com (Karl Heuer) (04/21/89)

In article <17016@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>If the declarations are within functions, `foo' and `bar' are not
>constants, but they are not lvalues.

According to the terminology used in the pANS, they are lvalues, but not
modifiable lvalues.

Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint