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".