msw@unix.cis.pitt.edu (Matt S Wartell) (06/21/91)
I was porting some code to a PC under Turbo C++ 1.0 and encountered some wierdness. Turbo C claims to be ANSI conformant, so I wanted to know if this is proper behavior. The code I am porting has its header files out of order, so one of the source files pre-processes into: /* declaration of function */ void add_version(int a, struct B *b); /* definition of structure */ struct B { ... }; /* definition of function */ void add_version(int a, struct B *b) { ... } When the compiler gets to the function definition, it complains of a type mismatch in parameter b. It is our impression that the compiler should produce an error at the function _declaration_ because the declaration uses an undefined, undeclared type. Does anyone know why the compiler did this, and whether or not it should have? Thanks in advance. -- matt wartell, university of pittsburgh msw@unix.cis.pitt.edu
volpe@camelback.crd.ge.com (Christopher R Volpe) (06/22/91)
In article <142762@unix.cis.pitt.edu>, msw@unix.cis.pitt.edu (Matt S Wartell) writes: |> /* declaration of function */ |> void add_version(int a, struct B *b); ^^^^^^^^ Implicit declaration of incomplete type whose scope is the prototype itself. You don't want this. |> |> /* definition of structure */ |> struct B { |> ... |> }; Declaration of new type not yet seen at this scope. This is fine. |> |> /* definition of function */ |> void add_version(int a, struct B *b) ^^^^^^^^ Reference to type already declared in outer scope above. This type is a DIFFERENT TYPE from the one that appears in the prototype declaration. |> { |> ... |> } |> |>When the compiler gets to the function definition, it complains of a type |>mismatch in parameter b. It is our impression that the compiler should |>produce an error at the function _declaration_ because the declaration |>uses an undefined, undeclared type. |>-- |>matt wartell, university of pittsburgh msw@unix.cis.pitt.edu The compiler is correct. Move the declaration of struct B before the prototype. -Chris ================== Chris Volpe G.E. Corporate R&D volpecr@crd.ge.com
mccrady@torolab6.vnet.ibm.com ("Don McCrady") (06/22/91)
> From: msw@unix.cis.pitt.edu (Matt S Wartell) > > /* declaration of function */ > void add_version(int a, struct B *b); /* 1 */ > > /* definition of structure */ > struct B { /* 2 */ > ... > }; > > /* definition of function */ > void add_version(int a, struct B *b) /* 3 */ > { > ... > } > > When the compiler gets to the function definition, it complains of a > type mismatch in parameter b. It is our impression that the compiler > should produce an error at the function _declaration_ ... A struct tag can be introduced before the structure has been defined, and is called an incomplete type. Thus, the declaration of function add_version() is entirely legal (but not too useful, as I'm about to explain). I've marked up your example with /* n */ to refer to specific lines. You should be getting an error message on or about the function definition (/* 3 */) because of C's scoping rules for function declarations. On the function declaration (/* 1 */), the left parenthesis that begins the parameter list opens a new scope. The following identifiers are local to that scope: a, B, and b. When the right parenthesis that ends the parameter list is seen, this scope closes, and all these identifiers disappear, including B. Note that B was an incomplete type that can never be completed, since nobody from an outside scope can peek inside this one. On /* 2 */, a new identifier B is introduced. Since we're at a different scope, this is an entirely different B than the one we introduced at /* 1 */. Just to show the distinction, I'll call this new identifier B' (B-prime). On /* 3 */, the compiler should notice that the definition of function add_version() does not match the original prototype. Why? Because the second parameter is different: the function declaration declared its second parameter to be a struct B *, and the function definition declared its second parameter to be a struct B' *. Not compatible, hence the error message. The real problem, as you mentioned, is that the declarations are out of order. If you had put the declaration for struct B before everything else, all occurrences of struct B would have resolved to the same identifier. ++don;