[comp.std.c] ref. to array != ptr

bhoughto@cmdnfs.intel.com (Blair P. Houghton) (11/09/90)

There are parts of the standard defining when an array
identifier _in_an_lvalue_context_ is converted to a pointer
to its first element and when it is not[1]; there are parts
that say that types are compatible essentially when they
are identical and not otherwise[2]; therefore,

	extern char *foo;

in one translation unit (e.g. loop.c) can not be
dereferenced to yield the first member of the object
defined by

	char foo[SIZE];

or

	char foo[] = "string";

in another translation unit (e.g., main.c).

It appears that one can, from the facts given[3], only
_infer_ this result.

My question (and I've just spent a butt-deadening hour
sitting in my chair hunched over the standard trying to
answer it for myself[4]) is:  is there anything more
explicit stating that the declaration of an externally-
defined pointer to Type can not specify an array of Type
with the same identifier defined externally?

One other thing stands to reason:  every time you use a
pointer to access an array, you have to define the pointer
and _assign_ the array's address to that pointer; it makes
no sense to redeclare array foo[] as a pointer in the same
translation unit in which it is defined, so that should not
lead you to do so in another translation unit.

[1] ANSI X3.159-1989, sec. 3.2.2.1, p. 37, ll. 15-19

[2] This is not strictly true (ibid. s. 3.1.2.6, p. 26, footnote 21)
but holds for pointer types (ibid., sec. 3.5.4.1, p. 67, ll. 24-25)
and array types (ibid., sec. 3.5.4.2, p. 68, ll. 11-12).

[3] That `foo' as used in (1) and (2) are not in an lvalue
context, and that a pointer is not identically an array

[4] Next time I'll open it.  :-)

				--Blair
				  "My other question is, how in the
				   hell did I never before make this
				   apparently easy mistake?"

gwyn@smoke.brl.mil (Doug Gwyn) (11/09/90)

In article <894@inews.intel.com> bhoughto@cmdnfs.intel.com (Blair P. Houghton) writes:
>  is there anything more explicit stating that the declaration of an
>externally-defined pointer to Type can not specify an array of Type
>with the same identifier defined externally?

Sure.  3.1.2.6:  "All declarations that refer to the same object or
function shall have compatible type; otherwise, the behavior is undefined."

bhoughto@cmdnfs.intel.com (Blair P. Houghton) (11/10/90)

In article <14391@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
>In article <894@inews.intel.com> bhoughto@cmdnfs.intel.com (Blair P. Houghton) writes:
>>  is there anything more explicit stating that the declaration of an
>>externally-defined pointer to Type can not specify an array of Type
>>with the same identifier defined externally?
>
>Sure.  3.1.2.6:  "All declarations that refer to the same object or
>function shall have compatible type; otherwise, the behavior is undefined."

Well, yes, I should have mentioned this as part of the inference;
I'm wondering if there isn't anything to the effect of "don't do
this" explicitly mentioning array/pointer confusions in multiple
translation units.

The more 3.1.2.6 and the definitions of compatible pointers and
compatible arrays sink in, though, the clearer the inference
becomes.  I was just hoping that, as was done for a number of
other things, there'd be an example of /*RIGHT*/ and /*WRONG*/
coding.

				--Blair
				  "cf. any of Henry's and
				   my stuff, respectively..."



A long example of the behavior is included below (silly me,
but I did this with Ultrix' cc, which isn't even a
conforming compiler).  I suggest you hit 'n' unless you've
never seen this situation before (although the difference
between the results of defining an array and declaring a
pointer and vice-versa are interesting, even if they
are undefined in conforming implementations).



3 Files (ex1.c, ex2.c, Makefile):

::::::::::::::
/eng/eng21/bhoughto/bin/experiment/ex1.c
::::::::::::::
/* ex1.c -- yahwp; used with ex2.c to show how not to declare external arrays */

/* choose a definition: */		/* proper corresponding declaration: */
#if DEF_AS_PTR
char *hello = "Hello, world!\n";	/* use DECL_AS_PTR in ex2.c */
#else
char hello[] = "Hello, world!\n";	/* use with not DECL_AS_PTR in ex2.c */
#endif

main()
{
    printf("%s\n",hello);
    foo();
}

::::::::::::::
/eng/eng21/bhoughto/bin/experiment/ex2.c
::::::::::::::
/* ex2.c -- the right and wrong way to declare an externally defined array */

/* choose a declaration: */		/* proper corresponding definition: */
#if DECL_AS_PTR
char *hello;				/* use iff DEF_AS_PTR in ex1.c */
#else
char hello[];				/* use iff not DEF_AS_PTR in ex1.c */
#endif

foo()
{
    printf("%s\n",hello);
}

::::::::::::::
/eng/eng21/bhoughto/bin/experiment/Makefile
::::::::::::::
#  testing external array/pointer declaration/confusion

# executable names encode value of (DEF_AS_PTR, DECL_AS_PTR)
external:  ex0 ex1 ex2 ex3

ex0:
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=0 -c ex1.c
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=0 -c ex2.c
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=0 -o ex0 ex1.o ex2.o

ex1:
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=1 -c ex1.c
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=1 -c ex2.c
	cc -DDEF_AS_PTR=0 -DDECL_AS_PTR=1 -o ex1 ex1.o ex2.o

ex2:
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=0 -c ex1.c
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=0 -c ex2.c
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=0 -o ex2 ex1.o ex2.o

ex3:
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=1 -c ex1.c
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=1 -c ex2.c
	cc -DDEF_AS_PTR=1 -DDECL_AS_PTR=1 -o ex3 ex1.o ex2.o



Results (name of executable encodes setting of (DEF_AS_PTR,DECL_AS_PTR):

Script started on Fri Nov  9 11:09:33 1990
prompt> ex0
Hello, world!

Hello, world!

prompt> ex1
Hello, world!

Segmentation fault (core dumped)
prompt> ex2
Hello, world!

8^P
prompt> ex3
Hello, world!

Hello, world!

prompt> ^D
script done on Fri Nov  9 11:10:03 1990

gwyn@smoke.brl.mil (Doug Gwyn) (11/10/90)

In article <906@inews.intel.com> bhoughto@cmdnfs.intel.com (Blair P. Houghton) writes:
-In article <14391@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes:
->In article <894@inews.intel.com> bhoughto@cmdnfs.intel.com (Blair P. Houghton) writes:
->=  is there anything more explicit stating that the declaration of an
->=externally-defined pointer to Type can not specify an array of Type
->=with the same identifier defined externally?
->Sure.  3.1.2.6:  "All declarations that refer to the same object or
->function shall have compatible type; otherwise, the behavior is undefined."
-Well, yes, I should have mentioned this as part of the inference;
-I'm wondering if there isn't anything to the effect of "don't do
-this" explicitly mentioning array/pointer confusions in multiple
-translation units.

No; taken in conjunction with the words that relate the identifier to
the object (and scope rules, and ...), the above is sufficient.

-The more 3.1.2.6 and the definitions of compatible pointers and
-compatible arrays sink in, though, the clearer the inference
-becomes.  I was just hoping that, as was done for a number of
-other things, there'd be an example of /*RIGHT*/ and /*WRONG*/
-coding.

There are an almost unlimited number of possible examples of stupid
mistakes.  Any decent C tutorial should already fully explain what the
relation is between array and pointer (and what it isn't).  There was
no new, subtle point introduced in the C standard that needed special
explanation, unlike most (or all?) of the other examples.  The usual
X3J11 response to requests for examples like the one you suggest was
"the standard is not a tutorial".