|
|
|
|
|
|
| Author |
Message |
neutron*star *nix forums Guru
Joined: 21 Feb 2005
Posts: 2039
|
Posted: Fri Jun 23, 2006 9:38 pm Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Fri Jun 23, 2006 9:53 pm Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Fri Jun 23, 2006 9:56 pm Post subject:
Re: Forward Declarations
|
|
|
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.
|
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
|
Posted: Fri Jun 23, 2006 10:22 pm Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Sat Jun 24, 2006 3:34 am Post subject:
Re: Forward Declarations
|
|
|
[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
|
Posted: Sat Jun 24, 2006 9:47 am Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Sat Jun 24, 2006 6:32 pm Post subject:
Re: Forward Declarations
|
|
|
| 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. 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
|
Posted: Sat Jun 24, 2006 7:51 pm Post subject:
Re: Forward Declarations
|
|
|
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.
|
<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
|
Posted: Mon Jun 26, 2006 6:41 pm Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Mon Jun 26, 2006 8:00 pm Post subject:
Re: Forward Declarations
|
|
|
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. }
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
|
Posted: Mon Jun 26, 2006 10:01 pm Post subject:
Re: Forward Declarations
|
|
|
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. }
|
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". 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
|
Posted: Mon Jun 26, 2006 10:06 pm Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Tue Jun 27, 2006 12:52 am Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Tue Jun 27, 2006 1:55 am Post subject:
Re: Forward Declarations
|
|
|
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
|
Posted: Tue Jun 27, 2006 2:03 am Post subject:
Re: Forward Declarations
|
|
|
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 |
|
 |
|
|
The time now is Fri Nov 21, 2008 6:53 am | All times are GMT
|
|
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
|
|