Help...

david.f.prosser dfp at cbnewsl.ATT.COM
Wed Oct 11 01:41:27 AEST 1989


In article <731 at carroll1.UUCP> dnewton at carroll1.cc.edu (Dave 'Yes, I'm weird' Newton) writes:
>Why doesn't this work?
>
>==========================
>#include <stdio.h>
>main ()
>{
>   char      h[];
>   scanf ("%s", h);
>   printf ("%s\n", h);
>}
>==========================
>
>  It seems innocent enuf, but just prints garbage.  I'm missing something
>obvious, but I'll be darned if I know what it is.

The C compiler you are using allowed you to declare an automatic array
of characters with an unspecified length.  The behavior of such a program
is undefined (and no diagnostic is required) according to the pANS.

Section 3.5, page 58, lines 30-31 (semantics):

	If an identifier for an object is declared with no linkage, the
	type for the object shall be complete by the end of its declarator,
	or by the end of its init-declarator if it has an initializer.

(An array with an unspecified length is an incomplete type.)

What some compilers have done (still do) is declare a zero-sized object
with an address on the stack.  If you are unlucky, when the scanf call
overwrites other parts of the stack, all that happens is that garbage
is printed.  What this program deserves is to dump core because the
return address for scanf's stack frame is overwritten.  This would let
you know (quickly) that something pretty basic is wrong.

A followup article asserted that "char h[];" in this context is the
same as "char *h;".  This is incorrect.  The latter declares a pointer
to one or more characters, but the value of the pointer is indeterminate
(uninitialized); such a pointer, when passed to scanf, will likewise
cause undefined behavior unless it is assigned a valid address.  The
former declaration, if accepted at all, most likely declares a zero-
length array, but at least its address is known, and if carefully
handled, can be useful.  (But not in the above example.)

Probably, this program wants a fixed-sized array of characters for h.
The following includes this and a few other changes as well.

	#include <stdio.h>
	main()
	{
		char h[1024];

		if (scanf("%1023s", h) == 1)	/* room for \0 */
			printf("%s\n", h);
		return 0;
	}

Dave Prosser	...not an official X3J11 answer...



More information about the Comp.lang.c mailing list