mikpe@majestix.ida.liu.se (Mikael Pettersson) (08/08/89)
I have a question for those who know the details about C declarations: What is the scope of the "type-name" in a cast expression? My impression is that the scope should be the entire surrounding expression (but not any further), but the compilers I've tried [PCC and GCC on a Sun3] both in fact make the type visible from the enclosing statement and downwards to the end of the {}-block. Example of code I think should be rejected: --huh.c-- /* accepted by PCC and GCC */ f() { int i; *(enum { foo, bar, bletch } *)&i = bar; i = foo; /* ?? */ } g() { int ia[2]; ((struct foo { int i,j; } *)ia)->i = 99; ia[1] = sizeof (struct foo); /* ?? */ } -- AdvTHANX for any references to the appropriate "chapter and verse". [RTFM? I have looked in both "The C Programming Language - Reference Manual" (UNIX PS1 4.3BSD) (essentially a reprint from K&R1) and "C: A Reference Manual, 2nd Ed." (Harbison&Steele) and found nil :-(] -- Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden email: mpe@ida.liu.se or ..!{mcvax,munnari,uunet}!enea!liuida!mpe
karl@haddock.ima.isc.com (Karl Heuer) (08/08/89)
In article <1324@majestix.ida.liu.se> mikpe@majestix.ida.liu.se (Mikael Pettersson) writes: >What is the scope of the "type-name" in a cast expression? >My impression is that the scope should be the entire surrounding >expression (but not any further), There is no such thing as "expression-scope" in C. Except for labels (which have function scope) and things declared within the parmlist of a non-defining function prototype declaration (which have prototype scope, a very short scope), each identifier has either block scope or file scope. In your examples, the identifiers have block scope. (Some clarifications: externally-declared static objects have file scope but internal linkage. Externally-declared non-static objects have file scope and external linkage, which used to be called "program scope". Function parameters have block scope, the block in question being the outermost block of the function; this differs from function scope, since parameter identifiers can be redeclared in an inner block, but label identifiers cannot.) Reference: 3.1.2.1 pANS. The same rules (except for prototypes) apply to pre-ANSI C, but the pANS has the most precise description I've seen. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
dfp@cbnewsl.ATT.COM (david.f.prosser) (08/09/89)
In article <1324@majestix.ida.liu.se> mikpe@majestix.ida.liu.se (Mikael Pettersson) writes: >I have a question for those who know the details about C declarations: > > What is the scope of the "type-name" in a cast expression? > >My impression is that the scope should be the entire surrounding >expression (but not any further), but the compilers I've tried >[PCC and GCC on a Sun3] both in fact make the type visible from >the enclosing statement and downwards to the end of the {}-block. These compilers are correct w.r.t. the ANSI C draft. Section 3.1.2.1: Structure, union, and enumeration tags have scope that begins just after the appearance of the tag in a type specifier that declares the tag. Each enumeration constant has scope that begins just after the appearance of its defining enumerator in an enumerator list. Any other identifier has scope that begins just after the completion of its declarator. In this same section, the location where scope ends is specified. For file scope, it ends at the end of the translation unit; for block scope, the } that ends the associate block; for function prototype scope, the end of the associated function declarator; and for function scope (labels), the } that ends the function. There is no such thing as "expression scope". Dave Prosser ...not an official X3J11 answer...
mikpe@majestix.ida.liu.se (Mikael Pettersson) (08/09/89)
In article <1324@majestix.ida.liu.se> I asked: > What is the scope of the "type-name" in a cast expression? > [example of legal, but ugly, code omitted] > >AdvTHANX for any references to the appropriate "chapter and verse". (Thanks to cris@mimsy (Chris Torek), mpl@attunix (Mike Lindner), karl@haddock (Karl Heuer) and dfp@cbnewsl (Dave Prosser) for pointing me in the right direction.) K&R1, the appendix, section 11.1: "Members and tags follow the same scope rules as other identifiers. The enum constants ... follow the same scope rules." ditto, section 8.5: "A structure [or union] specifier [of the form] struct identifier { struct-decl-list } declares the identifier to be the structure tag..." ditto, section 8.6: [enumeration tags behave just like struct/union tags] ditto, section 16.2: "type-name: type-specifier ... type-specifier: struct-or-union-specifier | ..." This means that the "type-name" in a cast (or sizeof) expression may introduce new names in the closest surrounding block. They are visible from the declaration point to the end of the block. Now why didn't I see this before :-( [at 1 AM !? gimme a break] (I'm in good company though; H&S-2nd ed. page 121 makes the same mistake: /* struct S is not defined here */ i = sizeof( struct S { ... }); /* OK, but strange */ j = sizeof( struct S ); /* probably illegal because struct S is still not defined */ :-> ) /Mike (p.s. In case you're wondering why on earth one would want to examine dubious constructs like these, it's because I'm working on a denotational definition for C. It'll be a rather messy one..) -- Mikael Pettersson, Dept of Comp & Info Sci, University of Linkoping, Sweden email: mpe@ida.liu.se or ..!{mcvax,munnari,uunet}!enea!liuida!mpe