Forward Declarations

Discussion in 'C Programming' started by Tom Plunket, Jun 23, 2006.

  1. Tom Plunket

    Tom Plunket Guest

    Hey gang;

    In C++ I often used forward declarations to allow me to get away with
    not including additional files in headers, if in fact all I needed was
    to know that a type existed.

    e.g.

    foo.h:
    struct Bar;
    void Foo(Bar* b);

    ....and then foo.cpp would presumably include bar.h, if in fact it
    needed to know what Bar consisted of.

    How can I accomplish a similar thing in (legal) C?

    I've tried the C++ forward-declaration strategy, e.g.

    struct Bar;
    void Foo(struct Bar* b);

    ....but I get a compilation failure when struct Bar is actually defined
    in a subsequent #include.

    I've also tried

    void Foo(struct Bar* b);

    ....all by itself, but that yields a compilation warning about the
    definition of struct Bar being only in the scope of this function.

    So, can I, and if I can, how can I accomplish what I'm trying to do in
    somewhat-pedantic, warning-free C?

    thx,
    -tom!
     
    Tom Plunket, Jun 23, 2006
    #1
    1. Advertising

  2. Tom Plunket said:

    > Hey gang;
    >
    > In C++ I often used forward declarations to allow me to get away with
    > not including additional files in headers, if in fact all I needed was
    > to know that a type existed.
    >
    > e.g.
    >
    > foo.h:
    > struct Bar;
    > void Foo(Bar* b);
    >
    > ...and then foo.cpp would presumably include bar.h, if in fact it
    > needed to know what Bar consisted of.


    Quite often, it doesn't need to know, and shouldn't be told. It is perfectly
    possible, and indeed commonplace, to put Bar's definition in bar.cpp, so
    that only bar.cpp can see it.

    >
    > How can I accomplish a similar thing in (legal) C?


    Just like that, except that it would have to be struct Bar * rather than
    just Bar *.

    > I've tried the C++ forward-declaration strategy, e.g.
    >
    > struct Bar;
    > void Foo(struct Bar* b);
    >
    > ...but I get a compilation failure when struct Bar is actually defined
    > in a subsequent #include.


    Then you did something wrong that we can't see.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jun 23, 2006
    #2
    1. Advertising

  3. Tom Plunket

    Tom Plunket Guest

    Richard Heathfield wrote:

    >> foo.h:
    >> struct Bar;
    >> void Foo(Bar* b);

    >
    >Quite often, it doesn't need to know, and shouldn't be told. It is
    >perfectly possible, and indeed commonplace, to put Bar's definition in
    >bar.cpp, so that only bar.cpp can see it.


    Sure; I do that in other languages frequently enough. I'm sort of a C
    newb, though, as 1) I haven't touched it in ten years, and 2) my
    exposure to it outside of college was working with people who didn't
    endeavor to expand their knowledge of the language. I first
    subscribed to comp.lang.c++ in 1996 though, as I needed to learn that
    language "for real". :)

    >Just like that, except that it would have to be struct Bar * rather
    >than just Bar *.


    Hmm. Can typedefs come into play here? E.g.

    struct Bar;
    typedef struct Bar Bar; // this is a common idiom in use here
    void Foo(Bar* b);

    So if this /should/ be legal, then yeah, I've got some other
    challenges in my environment. :)

    >Then you did something wrong that we can't see.


    Natch; in defense, though, the wrong thing was done long before I
    arrived on-scene. :)

    Thanks for your help.

    -tom!
     
    Tom Plunket, Jun 23, 2006
    #3
  4. Tom Plunket said:

    > Richard Heathfield wrote:
    >
    >>Just like that, except that it would have to be struct Bar * rather
    >>than just Bar *.

    >
    > Hmm. Can typedefs come into play here?


    Yes.

    <snip>
    >
    >>Then you did something wrong that we can't see.

    >
    > Natch; in defense, though, the wrong thing was done long before I
    > arrived on-scene. :)


    I'd like to help more,
    But even clc can't
    Make bricks without straw.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jun 23, 2006
    #4
  5. Tom Plunket

    Tom Plunket Guest

    Richard Heathfield wrote:

    >>>Then you did something wrong that we can't see.

    >>
    >> Natch; in defense, though, the wrong thing was done long before I
    >> arrived on-scene. :)

    >
    >I'd like to help more,
    >But even clc can't
    >Make bricks without straw.


    Right.

    I'll return with straw
    When I have found any more
    Alas, it's a chore

    ....and one that brings with it little business value. :)

    -tom!
     
    Tom Plunket, Jun 23, 2006
    #5
  6. Tom Plunket

    Chris Torek Guest

    [Tom Plunket's original example included the C fragment:]
    >>> struct Bar;
    >>> void Foo(struct Bar* b);

    [which is perfectly OK by itself. Richard Heathfield noted this
    and mentioned that if there was a problem, it must be something
    else that we cannot see here.]

    In article <>
    Tom Plunket <> wrote:
    >Hmm. Can typedefs come into play here? E.g.
    >
    >struct Bar;
    >typedef struct Bar Bar; // this is a common idiom in use here
    >void Foo(Bar* b);


    If the above is in "foo.h", and the following is in "bar.h":

    struct Bar;
    typedef struct Bar Bar;

    then a translation unit that uses this sequence:

    #include "foo.h"
    #include "bar.h"

    expands to the following fragments:

    struct Bar;
    typedef struct Bar Bar; // and a C99-only comment that \
    we hope is not so long that it wraps around and, oh dear, \
    good thing each of these lines ends with a backslash-newline
    void Foo(Bar* b);
    struct Bar;
    typedef struct Bar Bar;

    This goes wrong because in C (unlike C++) "benign re-typedefs" are
    invalid.

    There are a number of solutions, but the simplest is to drop the
    "typedef" lines entirely and spell out the word "struct" each time.
    (One more-complicated one is illustrated by:

    struct Bar;
    #ifndef BAR_TYPEDEF_DONE
    typedef struct Bar Bar;
    #define BAR_TYPEDEF_DONE
    #endif

    This 5-line sequence can appear in multiple header files; it makes
    sure that the "typedef" line appears exactly once, no matter how
    many of those headers are "#include"d.)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jun 24, 2006
    #6
  7. Chris Torek said:

    <snip>
    >
    > [...] expands to the following fragments:
    >
    > struct Bar;
    > typedef struct Bar Bar; // and a C99-only comment that \
    > we hope is not so long that it wraps around and, oh dear, \
    > good thing each of these lines ends with a backslash-newline
    > void Foo(Bar* b);
    > struct Bar;
    > typedef struct Bar Bar;
    >
    > This goes wrong because in C (unlike C++) "benign re-typedefs" are
    > invalid.
    >
    > There are a number of solutions, but the simplest is to drop the
    > "typedef" lines entirely and spell out the word "struct" each time.
    > (One more-complicated one is illustrated by:
    >
    > struct Bar;
    > #ifndef BAR_TYPEDEF_DONE
    > typedef struct Bar Bar;
    > #define BAR_TYPEDEF_DONE
    > #endif
    >
    > This 5-line sequence can appear in multiple header files; it makes
    > sure that the "typedef" line appears exactly once, no matter how
    > many of those headers are "#include"d.)


    Better still, he can keep his typedef and avoid the #ifndef by simply
    deciding on *one* header, suitably protected by inclusion guards, in which
    to place his forward declaration, and then making sure that header is
    included by any source that needs it.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jun 24, 2006
    #7
  8. Tom Plunket

    Chris Torek Guest

    >Chris Torek said:
    >> [...] expands to the following fragments:

    [from foo.h:]
    >> struct Bar;
    >> typedef struct Bar Bar;
    >> void Foo(Bar* b);

    [and then from bar.h:]
    >> struct Bar;
    >> typedef struct Bar Bar;
    >> This goes wrong because in C (unlike C++) "benign re-typedefs" are
    >> invalid.
    >>
    >> There are a number of solutions, but the simplest is to drop the
    >> "typedef" lines entirely and spell out the word "struct" each time.
    >> (One more-complicated one is illustrated by:
    >>
    >> struct Bar;
    >> #ifndef BAR_TYPEDEF_DONE
    >> typedef struct Bar Bar;
    >> #define BAR_TYPEDEF_DONE
    >> #endif
    >>
    >> This 5-line sequence can appear in multiple header files; it makes
    >> sure that the "typedef" line appears exactly once, no matter how
    >> many of those headers are "#include"d.)


    In article <>,
    Richard Heathfield <> wrote:
    >Better still, he can keep his typedef and avoid the #ifndef by simply
    >deciding on *one* header, suitably protected by inclusion guards, in which
    >to place his forward declaration, and then making sure that header is
    >included by any source that needs it.


    This method works, except when it does not. :)

    Consider the following:

    struct mutual1 {
    struct mutual1 *link;
    struct mutual2 *other;
    ... other data ...
    };

    struct mutual2 {
    struct mutual2 *link;
    struct mutual1 *other;
    ... other data ...
    };

    Clearly, there is no order in which these mutually-referential data
    structures can be defined so that each one is completely defined
    before the other one is defined.

    For those who insist on treating C as if it were C++, and writing
    typedefs for every "struct", the same situation arises when foo.h
    declares a function f() that operates on both a "struct foo *" and
    a "struct bar *", and bar.h declares a function b() that operates
    on both a "struct bar *" and a "struct foo *".

    Your challenge is to transform the following valid (and reasonable
    enough, albeit hardly complete) C code:

    % cat bar.h
    struct bar;

    struct bar *newbar(int arg1, const char *arg2);

    struct foo; /* in foo.h */
    void b(struct bar *this, struct foo *other);
    /* more stuff snipped */

    % cat foo.h
    struct foo;

    struct foo *newfoo(char *somearg);

    struct bar; /* in bar.h */
    void f(struct foo *this, struct bar *other);
    /* more stuff snipped */

    into the kind of pseudo-C++ that so many people seem to favor for
    some incomprehensible reason. :) Here b() must take a "Bar *"
    and a "Foo *", and f() must take a "Foo *" and a "Bar *".
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jun 24, 2006
    #8
  9. Chris Torek said:

    <snip>

    > In article <>,
    > Richard Heathfield <> wrote:
    >>Better still, he can keep his typedef and avoid the #ifndef by simply
    >>deciding on *one* header, suitably protected by inclusion guards, in which
    >>to place his forward declaration, and then making sure that header is
    >>included by any source that needs it.

    >
    > This method works, except when it does not. :)


    <g> Okay, so what did I miss?

    >
    > Consider the following:
    >
    > struct mutual1 {
    > struct mutual1 *link;
    > struct mutual2 *other;


    [and vice versa, so to speak]

    Ah yes. I heartily concede that I hadn't considered that. But, in my
    defence, I would suggest that the best way to deal with two such
    intertwined structures is to handle them both in the same module, in which
    case forward declarations for both can be put into the same header.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jun 24, 2006
    #9
  10. Tom Plunket

    Tom Plunket Guest

    Chris Torek wrote:

    >For those who insist on treating C as if it were C++...


    Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    put it in the standard do you figure?

    Anyway, thanks for your comments; it's helpful to find the useful
    information that exists therein.

    As it is, I'm faced with a codebase that has many features which are
    undesirable. The sad catch-22 is that I don't know what many of the
    problems are 'til I ask about them, and then get these little snipes
    along with the response. Hey, yeah, C99 allows the '//' comment. Oh
    my, intelligent adults will be unable to figure out how to deal with
    multiline comments! The end is nigh! Terr'ists surround us! ...that
    all besides the fact that when I was a wee lad the C compiler I used
    supported C++-style single-sine comments, and one tends to forget what
    features are in which standard when one uses more than one language.
    -tom!
     
    Tom Plunket, Jun 26, 2006
    #10
  11. Tom Plunket <> writes:
    > Chris Torek wrote:
    >>For those who insist on treating C as if it were C++...

    >
    > Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    > put it in the standard do you figure?


    C has no concept of "sin" other than the trigonometric function. :cool:}

    The idea that using typedefs for structure types is poor style is
    actually rather controversial. Chris Torek and I happen to agree on
    this point, but plenty of smart people don't.

    An argument in favor of using a typedef is that it provides a one-word
    name for a type. In my opinion, that's not a strong enough reason to
    use it.

    But typedefs are useful in other contexts. I ilke them for declaring
    complex pointer-to-function types, and the standard library defines
    typedefs for a number of integer type (size_t, int32_t, etc.).

    > Anyway, thanks for your comments; it's helpful to find the useful
    > information that exists therein.
    >
    > As it is, I'm faced with a codebase that has many features which are
    > undesirable. The sad catch-22 is that I don't know what many of the
    > problems are 'til I ask about them, and then get these little snipes
    > along with the response. Hey, yeah, C99 allows the '//' comment. Oh
    > my, intelligent adults will be unable to figure out how to deal with
    > multiline comments! The end is nigh! Terr'ists surround us! ...that
    > all besides the fact that when I was a wee lad the C compiler I used
    > supported C++-style single-sine comments, and one tends to forget what
    > features are in which standard when one uses more than one language.


    Yes, we do tend to snipe. We deal with a *lot* of inexperienced C
    programmers (some of whom have good questions but may not know the
    best way to ask them) and, unfortunately, with a fair number of
    deliberate trolls. At times our patience may wear a bit thin. We
    are, of course, only human, and we make mistakes (I made a doozy here
    just the other day). Ignore the snipes and you'll learn a lot here.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jun 26, 2006
    #11
  12. Tom Plunket

    Tom Plunket Guest

    Keith Thompson wrote:

    >> Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    >> put it in the standard do you figure?

    >
    >C has no concept of "sin" other than the trigonometric function. :cool:}


    Ah very good. ;)

    >The idea that using typedefs for structure types is poor style is
    >actually rather controversial. Chris Torek and I happen to agree on
    >this point, but plenty of smart people don't.


    Ok then. ;)

    It's been years since I "learned" C, but at the time the sage wisdom
    who was providing me with guidance said I should /always/ typedef
    structures, because a structure definition all by itself would yield
    an unnamed instance of that structure right at that location. E.g.

    struct something
    {
    int member;
    };

    This would deposit an unnamed "struct something" right there in the
    translation unit (if that's the proper C vocabulary, anyway) where the
    structure was defined. In these days of GHz processors an GB of RAM
    that "problem" would certainly be less of an issue, and dead-stripping
    linkers would also take care of it for you, but I don't feel too far
    out on a limb by thinking that The Almighty Standard says nothing of
    giga-anything nor of linking.

    >Yes, we do tend to snipe. We deal with a *lot* of inexperienced C
    >programmers (some of whom have good questions but may not know the
    >best way to ask them) and, unfortunately, with a fair number of
    >deliberate trolls.


    Kill filters set on "save my sanity". ;) Oof, they're not in The
    Standard, either.

    > Ignore the snipes and you'll learn a lot here.


    Heh, with any luck we'll have this project rolled over to C++ in no
    time at all. The gun's a lot more complicated but at least I
    understand how it works. :)

    thx,
    -tom!
     
    Tom Plunket, Jun 26, 2006
    #12
  13. Tom Plunket said:

    > Chris Torek wrote:
    >
    >>For those who insist on treating C as if it were C++...

    >
    > Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    > put it in the standard do you figure?


    It's not a sin at all. It's a blessing from dmr himself, and we should be
    grateful for it, and use it when it's appropriate to do so. Incidentally,
    as someone else has already pointed out, the real sin is in the math
    library. As it says in the Bible somewhere, don't cast stone[0] if you've
    included <math.h>.

    There are some smart people who think using typedef is a bad idea. I'm not
    among them. Does that mean I'm not smart? Well, maybe it does. But I think
    there's a lot of sense behind having a one-word name for a type. But I
    would not go so far as to hide a pointer in a typedef - not even for
    function pointers.

    > As it is, I'm faced with a codebase that has many features which are
    > undesirable. The sad catch-22 is that I don't know what many of the
    > problems are 'til I ask about them, and then get these little snipes
    > along with the response.


    You're allowed to treat those with a pinch of salt if they're undeserved.

    > Hey, yeah, C99 allows the '//' comment.


    That's nice. When C99 becomes as portable as C90 is now, it may even become
    relevant. :)

    > Oh
    > my, intelligent adults will be unable to figure out how to deal with
    > multiline comments! The end is nigh! Terr'ists surround us! ...that
    > all besides the fact that when I was a wee lad the C compiler I used
    > supported C++-style single-sine comments,


    Two coughs here. Firstly, single-sine? I thought we'd agreed it was sin!

    Secondly, they are actually BCPL-style comments, and dmr took the
    (presumably) deliberate (and, in my opinion, wise) decision to *omit* them
    from C. It is true that bs chose to include them into C++, but he did not
    invent them.

    > and one tends to forget what
    > features are in which standard when one uses more than one language.


    Certainly true, especially when the syntaxes (syntaces? syntaxii?) are
    ostensibly similar in so many ways.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at above domain (but drop the www, obviously)
     
    Richard Heathfield, Jun 26, 2006
    #13
  14. Tom Plunket <> writes:
    [...]
    > It's been years since I "learned" C, but at the time the sage wisdom
    > who was providing me with guidance said I should /always/ typedef
    > structures, because a structure definition all by itself would yield
    > an unnamed instance of that structure right at that location. E.g.
    >
    > struct something
    > {
    > int member;
    > };
    >
    > This would deposit an unnamed "struct something" right there in the
    > translation unit (if that's the proper C vocabulary, anyway) where the
    > structure was defined. In these days of GHz processors an GB of RAM
    > that "problem" would certainly be less of an issue, and dead-stripping
    > linkers would also take care of it for you, but I don't feel too far
    > out on a limb by thinking that The Almighty Standard says nothing of
    > giga-anything nor of linking.


    Hmm, I've never heard that argument. A struct declaration like the
    one above does not create an anonymous object. (Even if it did, since
    there would be no way to refer to it, any compiler worth its salt
    would optimize it away.)

    Logically, since this:

    struct something {
    int member;
    } x, y;

    creates two objects, and this:

    struct something {
    int member;
    } x;

    creates one object, then this:

    struct something {
    int member;
    };

    should create none.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jun 27, 2006
    #14
  15. Keith Thompson posted:


    > Logically, since this:
    >
    > struct something {
    > int member;
    > } x, y;
    >
    > creates two objects, and this:
    >
    > struct something {
    > int member;
    > } x;
    >
    > creates one object, then this:
    >
    > struct something {
    > int member;
    > };
    >
    > should create none.



    In the spirit of keeping things mathematical, maybe "should create zero
    objects" would be a better way of putting it? ; )


    --

    Frederick Gotham
     
    Frederick Gotham, Jun 27, 2006
    #15
  16. Tom Plunket posted:


    > struct something
    > {
    > int member;
    > };
    >
    > This would deposit an unnamed "struct something" right there in the
    > translation unit (if that's the proper C vocabulary, anyway) where the
    > structure was defined.



    Common sense tells me that that would be a whoefully redundant thing to do.

    Even in C++ -- where the definition of an object can result in the
    execution of code -- it would still be ridiculous (C++ is full of all sorts
    of optimizations like "Named Return Value Optimization").


    --

    Frederick Gotham
     
    Frederick Gotham, Jun 27, 2006
    #16
  17. Frederick Gotham <> writes:
    > Keith Thompson posted:
    >> Logically, since this:
    >>
    >> struct something {
    >> int member;
    >> } x, y;
    >>
    >> creates two objects, and this:
    >>
    >> struct something {
    >> int member;
    >> } x;
    >>
    >> creates one object, then this:
    >>
    >> struct something {
    >> int member;
    >> };
    >>
    >> should create none.

    >
    > In the spirit of keeping things mathematical, maybe "should create zero
    > objects" would be a better way of putting it? ; )


    In the spirit of reading and writing plain English, I thought (and
    still think) that the word "none" is perfectly clear.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jun 27, 2006
    #17
  18. On Mon, 26 Jun 2006 15:01:00 -0700, Tom Plunket <>
    wrote:

    <snip>
    > It's been years since I "learned" C, but at the time the sage wisdom
    > who was providing me with guidance said I should /always/ typedef
    > structures, because a structure definition all by itself would yield
    > an unnamed instance of that structure right at that location. E.g.
    >
    > struct something
    > {
    > int member;
    > };
    >

    Does not, and never did, as already said.

    Are you sure you, or your guide, didn't misunderstand or misremember
    the issue of including or omitting a struct _tag_?

    struct { elements } zorg;
    creates an 'anonymous' struct type, which you cannot refer to later --
    i.e. you cannot create another variable, or a pointer to one, or a
    function argument, etc., which the compiler will recognize as the same
    type. (Unlike some other non-C languages, which do use so called
    'structural' or 'deep' type compatibility.)

    struct good { elements } lelu;
    creates a variable _and_ a tag (type) which you can use later.
    struct good { elements };
    creates _only_ the tag (type). Which you can use later,
    and that is the only way to use it, so if you don't, it's useless :)

    <OT> In C++, the tag name(s) in the latter form are available as
    typenames by themselves, in addition to 'struct good' as in C (which
    is still permitted). People often say loosely that C++ automatically
    does typedef for you, but this isn't strictly right; even in C++ you
    can still declare both an ordinary-identifier foo and a tag foo in the
    same scope, but it is very bad style, even worse than it is in C.

    - David.Thompson1 at worldnet.att.net
     
    Dave Thompson, Jul 10, 2006
    #18
  19. Tom Plunket

    Guest

    Keith Thompson wrote:
    > Tom Plunket <> writes:
    > > Chris Torek wrote:
    > >>For those who insist on treating C as if it were C++...

    > >
    > > Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    > > put it in the standard do you figure?

    >
    > C has no concept of "sin" other than the trigonometric function. :cool:}
    >
    > The idea that using typedefs for structure types is poor style is
    > actually rather controversial. Chris Torek and I happen to agree on
    > this point, but plenty of smart people don't.
    >
    > An argument in favor of using a typedef is that it provides a one-word
    > name for a type. In my opinion, that's not a strong enough reason to
    > use it.


    Usually the best argument in favor of using a typedef
    is that the name defined reflects how you want client
    code to view the type.

    If client code should view the type as opaque, then
    using typedef for a struct type makes sense.

    If client code should view a struct transparently,
    then no typedef - just use struct.

    In my programming, I tend to use abstraction rather
    a lot, so usually types are typedef'ed. But I
    understand both modes, and use either, as appropriate.

    There is one typedef idiom that bears mentioning:

    typedef struct { ... } *Foo;

    This idiom is useful when the underlying structs
    should always be malloc'ed, never static or auto.
    Because of how the type is declared, no code will
    have these structs other than {m,c,re}alloc()'ed
    ones.
     
    , Jul 17, 2006
    #19
  20. writes:
    > Keith Thompson wrote:
    >> Tom Plunket <> writes:
    >> > Chris Torek wrote:
    >> >>For those who insist on treating C as if it were C++...
    >> >
    >> > Ah, I didn't realize what a sin it was to use 'typedef'. Why'd they
    >> > put it in the standard do you figure?

    >>
    >> C has no concept of "sin" other than the trigonometric function. :cool:}
    >>
    >> The idea that using typedefs for structure types is poor style is
    >> actually rather controversial. Chris Torek and I happen to agree on
    >> this point, but plenty of smart people don't.
    >>
    >> An argument in favor of using a typedef is that it provides a one-word
    >> name for a type. In my opinion, that's not a strong enough reason to
    >> use it.

    >
    > Usually the best argument in favor of using a typedef
    > is that the name defined reflects how you want client
    > code to view the type.
    >
    > If client code should view the type as opaque, then
    > using typedef for a struct type makes sense.
    >
    > If client code should view a struct transparently,
    > then no typedef - just use struct.
    >
    > In my programming, I tend to use abstraction rather
    > a lot, so usually types are typedef'ed. But I
    > understand both modes, and use either, as appropriate.
    >
    > There is one typedef idiom that bears mentioning:
    >
    > typedef struct { ... } *Foo;
    >
    > This idiom is useful when the underlying structs
    > should always be malloc'ed, never static or auto.
    > Because of how the type is declared, no code will
    > have these structs other than {m,c,re}alloc()'ed
    > ones.


    In that case, it would probably make sense to hide the *alloc() and
    free() calls behind some type-specific functions; the *alloc()
    wrappers could also do any necessary initialization of the struct
    members. This is basically what fopen() and fclose() do, except that
    the pointer isn't hidden behind a typedef; the members of the
    structure are effectively hidden not by the fact that there's no name
    for the structure type (there is, FILE), but by the fact that the
    details are undocumented, and code that depends on them will break
    when ported.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jul 17, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. matthew polder

    namespaces and forward declarations

    matthew polder, Jul 24, 2003, in forum: C++
    Replies:
    1
    Views:
    361
    John Harrison
    Jul 24, 2003
  2. mjm
    Replies:
    3
    Views:
    406
  3. whithers
    Replies:
    4
    Views:
    379
    Sumit Rajan
    Jan 16, 2004
  4. Alan Lee
    Replies:
    5
    Views:
    362
    Rolf Magnus
    Apr 5, 2004
  5. Steven T. Hatton

    forward declarations and namespaces?

    Steven T. Hatton, Apr 27, 2004, in forum: C++
    Replies:
    6
    Views:
    3,251
    Dave Moore
    May 5, 2004
Loading...

Share This Page