Why doesn't this work?

Chris Torek chris at mimsy.UUCP
Thu Mar 23 20:31:57 AEST 1989


In article <1309 at dukeac.UUCP> sbigham at dukeac.UUCP (Scott Bigham) writes:
>typedef char **Block;
>
>Block
>	b1 ={"this","that"},
>	b2={"yes","no"},
>	B[]={b1,b2};

It does not work because b1, b2, and B[any] have type `pointer to
pointer to char' and the first two { ... } lines are not valid initialisers
for pointer-to-pointer-to-char, and indeed are not valid initialisers
for anything but array-of-pointer-to-char.  (The third initialiser would
be correct if the first two were not rejected earlier.)

The following rerun makes various salient points.

From: chris at umcp-cs.UUCP (Chris Torek)
Newsgroups: net.lang.c
Subject: Re: C Coding Question
Date: 16 Aug 86 00:58:44 GMT

In many articles many USENET posters assert that
>... about "char *help[]" and "char **help": the two forms are IDENTICAL
>to virtually every C compiler (that's worth its salt).  Arrays in C are
>merely special cases of pointers.  In other words, both forms are correct.

	NO!

Ai!  This has been asserted far too often.  Arrays and pointers are
not at all the same thing in C!

Section 5.3 of K&R 1st ed. has this to say about it:

  The correspondence between indexing and pointer arithmetic is
  evidently very close. ... The effect is that an array name *is*
  a pointer expression.  (p. 94)

This does not say that arrays and pointers are *the same*.

  There is one difference between an array name and a pointer
  that must be kept in mind.

Aha!  See p. 94 for that difference.

  As formal parameters in a function defintion,

	char s[];

  and

	char *s;

  are exactly equivalent.... (p. 95)

Here they *are* the same---but note the qualifier: `As formal
parameters'.  The array must not be a global or static variable.

There is one other thing which, I guess, adds to this confusion.
Both of the following are legal global declarations in C:

	char	msg0[] = "Hello, world";
	char	*msg1 = "Hello, world";

Given both declarations,

	printf("%s\n", msg0);

and

	printf("%s\n", msg1);

produce the same output.  Yet msg0 and msg1 are not the same:

	printf("%d %d\n", sizeof (msg0), sizeof (msg1));

prints

	13 4

on a Vax; for msg0 is an array, and msg1 is a pointer.  The code
generated for the two declarations is different:

	/* edited assembly output from ccom */
		.data			# Switch to data segment.
		.globl	_msg0		# The array ...
	_msg0:	.asciz	"Hello, world"	# and here it is.

		.data	2		# Switch to alternate data segment.
	L12:	.asciz	"Hello, world"	# The object to which msg1 will point.
		.data			# Back to regular data segment.
		.globl	_msg1		# The pointer ...
	_msg1:	.long	L12		# which points to the object.

String constants comprise two special cases in the compiler.  The
first case is when the constant appears anywhere *except* as an
initialiser for a `char' array.  Here the compiler uses the alternate
data segment to suddenly `create' a new array, initialised to the
string text; it then generates a pointer to that array.  In the
second case the string constant is generated in the primary data
segment, and `is' the array being initialised: the constant is
`unwrapped' into an aggregate initialisation.

The second case is actually the more `conventional' of the two;
other aggregates cannot be created at run time:

	int a[] = { 0, 1, 2, 3 };

is legal only outside functions.  What seems surprising to some is
that the same is true of

	char s[] = "foo";

because, unwrapped, this is equivalent to

	char s[] = { 'f', 'o', 'o', '\0' };
	
---even though

	char *s = "foo";

is legal anywhere a declaration is legal.

Ah, if only C had aggregate initialisers!
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list