From: scs@adam.mit.edu (Steve Summit)
Subject: string literal initializers
Organization: none, at the moment
Date: Wed, 14 Oct 1992 20:04:05 GMT

[The questions I am about to ask seem fairly obvious; apologies
if they have been discussed here before.]

Is the translation unit

	char a1[2] = "abc";

required to elicit a diagnostic?  In (what will be seen to be) a
similar vein, is the program

	#include <stdio.h>
	main()
	{
	char a2[5] = "def";
	printf("%d\n", a2[4]);
	return 0;
	}

required to print a zero?

If ANSI X3.159 addresses these questions, we would expect to find
the answers in section 3.5.7 .  However, the only constraint that
might be violated (and hence require a diagnostic) by a1's
initialization is

	There shall be no more initializers in an initializer
	list than there are objects to be initialized.
	[ANSI X3.159-1989 sec. 3.5.7 p. 72 line 30]

, but a strict (and, I think, arguably correct) reading of the
syntax description would show that a2's initializer list contains
only one initializer (a single string literal).

The problems here boil down to the fact that the language
describing string literal (and wide string literal)
initialization appears only in the semantics section,
and is incomplete:

	An array of character type may be initialized by a
	character string literal, optionally enclosed in braces.
	Successive characters of the character string literal
	(including the terminating null character if there is
	room or if the array is of unknown size) initialize the
	elements of the array.
	[sec. 3.5.7 p. 73 lines 13-15]

This does not say what happens if there is not room for
characters other than the terminating null character,
as in a1's case.

	If there are fewer initializers in a brace-enclosed list
	than there are members of an aggregate, the remainder of
	the aggregate shall be initialized implicitly the same as
	objects that have static storage duration.
	[sec. 3.5.7 p. 73 lines 32-34]

This does not necessarily apply to a2's initialization.  First of
all (though admittedly pretty nit-picky), a2's initialization is
not enclosed in braces.  Secondly, there is approximately the
same discrepancy here between the concepts "number of
initializers in an initializer list" and "number of characters in
a string literal."  Therefore, while a2[4] should probably
receive a 0 (as if a2 had static duration), I'm not sure I could
fault an implementation that left it uninitialized.

These questions could be answered if string literal initializers
were defined to be exactly equivalent to brace-enclosed lists of
character constants, i.e.

	char a1[2] = {'a', 'b', 'c'};
	char a2[5] = {'d', 'e', 'f', '\0'};

However, the only statement that suggests a strict identity
of the two forms appears in an example [sec. 3.5.7, p. 75,
lines 24-29], and is thus not part of the standard.

Based on my reading of the current standard, I am tending towards
a conclusion that the behavior in both these cases is undefined.
("Undefined behavior is otherwise indicated in this standard...
by the omission of any explicit definition of behavior."
[sec. 1.6 p. 3 lines 43-44])

These questions seem worthy of an interpretation ruling, if
anyone really cares.  The abridged list of interpretation rulings
Chris Volpe posted last August does not appear to cover them.
(Speaking of lists of interpretations, someone should re-post the
full list, of which Chris had and posted only the index.  Or have
I missed that, too?)

It is obvious that a high-quality implementation would issue a
diagnostic for a1, whether required or not.  I'm not so sure
about the obvious, quality initialization of a2[4].

(For what it's worth, gcc does issue a diagnostic for a1,
and does clear (with bzero!) a2[4] on entry.)

					Steve Summit
					scs@adam.mit.edu
Newsgroups: comp.std.c