niXforums Forum Index
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   PreferencesPreferences   Log in to check your private messagesLog in to check your private messages   Log inLog in 
·  nixdoc.net ·  man pages ·  Linux HOWTOs ·  FreeBSD Tips ·  Forums
navigation Forum index » Programming » C
Forward Declarations
Post new topic   Reply to topic Page 1 of 2 [24 Posts] View previous topic :: View next topic
Goto page:  1, 2 Next
Author Message
neutron*star
*nix forums Guru


Joined: 21 Feb 2005
Posts: 2039

PostPosted: Fri Jun 23, 2006 9:38 pm    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket said:

Quote:
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.

Quote:

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

Quote:
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)
Back to top
Tom Plunket
*nix forums beginner


Joined: 09 Apr 2005
Posts: 25

PostPosted: Fri Jun 23, 2006 9:53 pm    Post subject: Re: Forward Declarations Reply with quote

Richard Heathfield wrote:

Quote:
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". :)

Quote:
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. :)

Quote:
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!
Back to top
neutron*star
*nix forums Guru


Joined: 21 Feb 2005
Posts: 2039

PostPosted: Fri Jun 23, 2006 9:56 pm    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket said:

Quote:
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>
Quote:

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

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)
Back to top
Tom Plunket
*nix forums beginner


Joined: 09 Apr 2005
Posts: 25

PostPosted: Fri Jun 23, 2006 10:22 pm    Post subject: Re: Forward Declarations Reply with quote

Richard Heathfield wrote:

Quote:
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!
Back to top
Chris Torek
*nix forums Guru


Joined: 26 Feb 2005
Posts: 481

PostPosted: Sat Jun 24, 2006 3:34 am    Post subject: Re: Forward Declarations Reply with quote

[Tom Plunket's original example included the C fragment:]
Quote:
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 <9coo92dotot68bm3osc57jta7h2ig57a7c@4ax.com>
Tom Plunket <gamedev@fancy.org> wrote:
Quote:
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.
Back to top
neutron*star
*nix forums Guru


Joined: 21 Feb 2005
Posts: 2039

PostPosted: Sat Jun 24, 2006 9:47 am    Post subject: Re: Forward Declarations Reply with quote

Chris Torek said:

<snip>
Quote:

[...] 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)
Back to top
Chris Torek
*nix forums Guru


Joined: 26 Feb 2005
Posts: 481

PostPosted: Sat Jun 24, 2006 6:32 pm    Post subject: Re: Forward Declarations Reply with quote

Quote:
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 <ya-dndQ81dCAlwDZRVnyuw@bt.com>,
Richard Heathfield <invalid@invalid.invalid> wrote:
Quote:
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. Smile 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.
Back to top
neutron*star
*nix forums Guru


Joined: 21 Feb 2005
Posts: 2039

PostPosted: Sat Jun 24, 2006 7:51 pm    Post subject: Re: Forward Declarations Reply with quote

Chris Torek said:

<snip>

Quote:
In article <ya-dndQ81dCAlwDZRVnyuw@bt.com>,
Richard Heathfield <invalid@invalid.invalid> 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. Smile

<g> Okay, so what did I miss?

Quote:

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)
Back to top
Tom Plunket
*nix forums beginner


Joined: 09 Apr 2005
Posts: 25

PostPosted: Mon Jun 26, 2006 6:41 pm    Post subject: Re: Forward Declarations Reply with quote

Chris Torek wrote:

Quote:
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!
Back to top
Keith Thompson
*nix forums Guru


Joined: 28 Feb 2005
Posts: 5173

PostPosted: Mon Jun 26, 2006 8:00 pm    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket <gamedev@fancy.org> writes:
Quote:
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.).

Quote:
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) kst-u@mib.org <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.
Back to top
Tom Plunket
*nix forums beginner


Joined: 09 Apr 2005
Posts: 25

PostPosted: Mon Jun 26, 2006 10:01 pm    Post subject: Re: Forward Declarations Reply with quote

Keith Thompson wrote:

Quote:
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. ;)

Quote:
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.

Quote:
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". Wink Oof, they're not in The
Standard, either.

Quote:
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!
Back to top
neutron*star
*nix forums Guru


Joined: 21 Feb 2005
Posts: 2039

PostPosted: Mon Jun 26, 2006 10:06 pm    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket said:

Quote:
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.

Quote:
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.

Quote:
Hey, yeah, C99 allows the '//' comment.

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

Quote:
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.

Quote:
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)
Back to top
Keith Thompson
*nix forums Guru


Joined: 28 Feb 2005
Posts: 5173

PostPosted: Tue Jun 27, 2006 12:52 am    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket <gamedev@fancy.org> writes:
[...]
Quote:
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) kst-u@mib.org <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.
Back to top
Frederick Gotham
*nix forums Guru


Joined: 09 Jun 2006
Posts: 502

PostPosted: Tue Jun 27, 2006 1:55 am    Post subject: Re: Forward Declarations Reply with quote

Keith Thompson posted:


Quote:
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
Back to top
Frederick Gotham
*nix forums Guru


Joined: 09 Jun 2006
Posts: 502

PostPosted: Tue Jun 27, 2006 2:03 am    Post subject: Re: Forward Declarations Reply with quote

Tom Plunket posted:


Quote:
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
Back to top
Google

Back to top
Display posts from previous:   
Post new topic   Reply to topic Page 1 of 2 [24 Posts] Goto page:  1, 2 Next
View previous topic :: View next topic
The time now is Fri Nov 21, 2008 6:53 am | All times are GMT
navigation Forum index » Programming » C
Jump to:  

Similar Topics
Topic Author Forum Replies Last Post
No new posts forward to originator cnschulz Postfix 0 Thu May 08, 2008 4:41 am
No new posts Newbie question: How to forward a domain to a mailbox? leei Postfix 0 Fri Aug 24, 2007 4:55 pm
No new posts mail forward warrenchua PHP 0 Fri Jul 21, 2006 1:32 pm
No new posts Reverse proxying through a forward proxy? Joost de Heer Apache 0 Fri Jul 21, 2006 9:38 am
No new posts equivalent of MAIL>SET FORWARD/USER=ME YOU on unix VAXman-@SendSpamHere.ORG VMS 4 Thu Jul 20, 2006 7:56 pm

ADD Coaches | Credit Check | Loans | Mobile Phones | Electricity Suppliers
Copyright © 2004-2005 DeniX Solutions SRL
 
Other DeniX Solutions sites: Unix/Linux blog |  electronics forum |  medicine forum |  science forum | 
Privacy Policy


Powered by phpBB © 2001, 2005 phpBB Group
[ Time: 0.2974s ][ Queries: 16 (0.1343s) ][ GZIP on - Debug on ]