undefined type in arg list vs. return type 
Author Message
 undefined type in arg list vs. return type

if i have a function prototype that uses some as-yet-undefined type in
its argument list, i get a compilation error.  but if i have a
prototype which *returns* that type, all is well.  i am a bit curious
why this is so.

for example:

  ratbert% cat type.c
  #include <stdio.h>
  #include <stdlib.h>

  struct struct_one f1(struct struct_one s1);
  int f2(struct struct_two s2);

  struct struct_one
  {
    int element_one;
  };

  struct struct_two
  {
    int element_two;
  };

  struct struct_one f1(struct struct_one s1)
  {
    s1.element_one = 1;
  }

  int f2(struct struct_two s2)
  {
    s2.element_two = 2;
  }

  int main(void)
  {
    struct struct_one ms1;
    struct struct_two ms2;

    ms1.element_one = 9;
    ms2.element_two = 5;

    return EXIT_SUCCESS;
  }
  ratbert% cc type.c
  "type.c", line 5: warning: dubious tag declaration: struct struct_two
  "type.c", line 23: identifier redeclared: f2
          current : function(struct struct_two {int element_two}) returning int
          previous: function(struct element_one {}) returning int : "type.c", line 5
  cc: acomp failed for type.c

the compiler complains about f2, but not f1.  the only difference i can see
is that the prototype for f1 has an as-yet-unknown type as the return type,
and f2 has the as-yet-unknown type in the argument list.

---
John Gordon                  "No Silicon Heaven?  Preposterous!  Where would



Fri, 26 Oct 2001 03:00:00 GMT  
 undefined type in arg list vs. return type

Quote:

>if i have a function prototype that uses some as-yet-undefined type in
>its argument list, i get a compilation error.  but if i have a
>prototype which *returns* that type, all is well.  i am a bit curious
>why this is so.

This is actually a FAQ:

11.5:   Why does the declaration

                extern int f(struct x *p);

        give me an obscure warning message about "struct x introduced in
        prototype scope"?

A:      In a quirk of C's normal block scoping rules, a structure
        declared (or even mentioned) for the first time within a
        prototype cannot be compatible with other structures declared in
        the same source file (it goes out of scope at the end of the
        prototype).

        To resolve the problem, precede the prototype with the vacuous-
        looking declaration

                struct x;

        which places an (incomplete) declaration of struct x at file
        scope, so that all following declarations involving struct x can
        at least be sure they're referring to the same struct x.

        References: ISO Sec. 6.1.2.1, Sec. 6.1.2.6, Sec. 6.5.2.3.

[Example edited way down]

Quote:
>  struct struct_one f1(struct struct_one s1);
>  int f2(struct struct_two s2);
>  ratbert% cc type.c
>  "type.c", line 5: warning: dubious tag declaration: struct struct_two

This is the important message.  No diagnostic is required here, but
better compilers give one.  No matter what they emit, people seem to
get confused by it.  GCC says, for instance:

        stdin:1: warning: `struct x' declared inside parameter list
        stdin:1: warning: its scope is only this definition or declaration,
        stdin:1: warning: which is probably not what you want.

Quote:
>  "type.c", line 23: identifier redeclared: f2
>          current : function(struct struct_two {int element_two}) returning int
>          previous: function(struct element_one {}) returning int : "type.c", line 5

This diagnostic shows that the compiler has a bug.  The previous
declaration (from line 5 -- the only line I retained in the edit
above) gives the first parameter the type:

        struct tag_that_is_at_a_scope_that_is_not_accessible_here_but_\
        was_spelled_struct_two_when_it_was_accessible

which was an incomplete type at the time.  This type was never
completed, and its tag is not "element_one".

This occurs because in C, the keyword "struct", followed by a tag
"T", followed by an open brace "{", means:

        "define a new type T, using the contents to the matching }
        as its elements"

Without a tag, it means the same thing; it is just that the type
has no tag-name.  Without a semicolon, but with tag T, it means one
of two things:

        "refer back to the most recent definition of type T"

or:

        "since this is an inner scope than the most recent definition
        of type T, hide the current definition of type T and open
        up a new incomplete definition of type T in the current
        scope."

(The latter is trivially accomplished when there is no most recent
definition of type T.  It is what you get when you write "struct x;"
at file scope, as recommended in the FAQ.)
--
In-Real-Life: Chris Torek, Berkeley Software Design Inc




Fri, 26 Oct 2001 03:00:00 GMT  
 undefined type in arg list vs. return type

Quote:

> if i have a function prototype that uses some as-yet-undefined type in
> its argument list, i get a compilation error.  but if i have a
> prototype which *returns* that type, all is well.  i am a bit curious
> why this is so.

The answer to the question as stated is `technicality' which the
committee reaffirmed.  

But the problem you are illustrating is something else altogether!

Quote:

> for example:

>   ratbert% cat type.c
>   #include <stdio.h>
>   #include <stdlib.h>

>   struct struct_one f1(struct struct_one s1);

This technically counts as a definition (and not merely a declaration)
of s1.  As the type is incomplete, this is incorrect.

Quote:
>   int f2(struct struct_two s2);

This has the additional problem that struct struct_two is in a new
struct type which cannot be completed because it is in an inner scope!

The problem is that in the previous example, struct struct_one had been
seen in the outer scope (because of the return type specification) when
the parameter list was scanned, and hence the latter did not introduce a
new type in the inner scope.  To get to the same situation as the
previous example, you have to write:

  struct struct_two; int f2(struct struct_two s2);

Quote:

>   struct struct_one
>   {
>     int element_one;
>   };

This refers to the same `struct struct_one' type mentioned before.

Quote:
>   struct struct_two
>   {
>     int element_two;
>   };

This one does not.

Quote:
>   struct struct_one f1(struct struct_one s1)
>   {
>     s1.element_one = 1;
>   }

So this declaration is correct (except for the technicality mentioned
above.)

Quote:

>   int f2(struct struct_two s2)
>   {
>     s2.element_two = 2;
>   }

This one is incorrect.  The parameter type now refers to the previously
seen struct struct_two from the file scope.  The previous declaration
used  a different parameter type (a struct struct_two which was a new
type in parameter scope).

Quote:
>   int main(void)
>   {
>     struct struct_one ms1;
>     struct struct_two ms2;

>     ms1.element_one = 9;
>     ms2.element_two = 5;

>     return EXIT_SUCCESS;
>   }
>   ratbert% cc type.c
>   "type.c", line 5: warning: dubious tag declaration: struct struct_two
>   "type.c", line 23: identifier redeclared: f2
>           current : function(struct struct_two {int element_two}) returning int
>           previous: function(struct element_one {}) returning int : "type.c", line 5
>   cc: acomp failed for type.c

> the compiler complains about f2, but not f1.  the only difference i can see
> is that the prototype for f1 has an as-yet-unknown type as the return type,
> and f2 has the as-yet-unknown type in the argument list.

No. The difference was that the struct tag was seen in the outer scope
when it came to the parameter list for f1, but not for f2.
---


Fri, 26 Oct 2001 03:00:00 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. Help with: C2392 - covariant returns types are not supported in managed types

2. HRESULT return type turns into void when adding class from type library

3. type *var -- vs. -- type* var

4. value types vs. reference types

5. C# Base Types vs. .NET Types

6. C# Types vs. SQL Types (kinda urgent)

7. Type Casting between Base and Derived Type (Serialization of objects with Type members)

8. Variables and types of type "Type"

9. determine arg types of a function

10. qsort comparison function arg types

11. float (type) arg problem

12. As-yet-undefined function type as struct member?

 

 
Powered by phpBB® Forum Software