473,657 Members | 2,624 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Forward Declarations

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!
Jun 23 '06 #1
28 1964
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)
Jun 23 '06 #2
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!
Jun 23 '06 #3
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)
Jun 23 '06 #4
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!
Jun 23 '06 #5
[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 <9c************ *************** *****@4ax.com>
Tom Plunket <ga*****@fancy. org> 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_DON E
typedef struct Bar Bar;
#define BAR_TYPEDEF_DON E
#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.
Jun 24 '06 #6
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_DON E
typedef struct Bar Bar;
#define BAR_TYPEDEF_DON E
#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)
Jun 24 '06 #7
>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_DON E
typedef struct Bar Bar;
#define BAR_TYPEDEF_DON E
#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************ ********@bt.com >,
Richard Heathfield <in*****@invali d.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. :-)

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 incomprehensibl e 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.
Jun 24 '06 #8
Chris Torek said:

<snip>
In article <ya************ ********@bt.com >,
Richard Heathfield <in*****@invali d.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?

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)
Jun 24 '06 #9
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!
Jun 26 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
5462
by: mjm | last post by:
Folks, Please help me with the following problems: ******************************************** 1. I have a class template template<class Base> class Matrix : public Base { /* .... */ }
10
2222
by: Alan Lee | last post by:
Hi i am writing a small simulation for a bunch of atoms jumping around on a surface. I know i am a crappy programmer since i am not very familiar with object oriented languages. I am woindering if anyone can tell me why my forward class declarations not working. the member function findpaths can't seem to access the class Board when I try to pass it a board object by value. I put the Board class latrerbut also put in a forward...
6
5199
by: Steven T. Hatton | last post by:
Should I be able to forward declare something from a namespace different from the current one? For example the following code compiles: //testdriver.hpp #ifndef TESTDRIVER_HPP #define TESTDRIVER_HPP #include <ostream> namespace ns_testdriver{ using std::ostream;
11
2427
by: aleko | last post by:
This applies equally to function prototypes. Why do we have to tell the compiler twice? Other modern compiled languages don't have this requirement. Just curious, Aleko
12
12159
by: fox | last post by:
How do I (portably) make a forward reference to a static (I mean file-scope) variable? I've been using "extern" for years, for example: extern int x; int foo(void) { return x++; }
23
3841
by: mark.moore | last post by:
I know this has been asked before, but I just can't find the answer in the sea of hits... How do you forward declare a class that is *not* paramaterized, but is based on a template class? Here's what I thought should work, but apparently doesn't: class Foo; void f1(Foo* p)
2
508
by: Carlos Martinez Garcia | last post by:
Hi all: I usually make forward declarations in headers. Something like this: class MyClass; Now, I need a reference to a type defined like this (traditional C Style): typedef struct {
6
8612
by: Hunk | last post by:
Hi I have a question on usage of forward declarations of templates. While searching through this group , people suggested using forward declarations and typedefs for templates as // in myfile.h template<typename T,typename R> class some_class;
11
8310
by: Jef Driesen | last post by:
I have the following problem in a C project (but that also needs to compile with a C++ compiler). I'm using a virtual function table, that looks like this in the header file: typedef struct device_t { const device_backend_t *backend; ... } device_t; typedef struct device_backend_t {
0
1467
by: Rune Allnor | last post by:
Hi all. I have these classes, implemented as templates in header files. Right now I have one file per class, where both the declarations and implementations of one class are located in each file. I would like to apply the visitor pattern to some of these classes. One of the technicalities behind the visitor pattern is that one needs forward declarations of classes, since there are two class hierarchies which refer to each other.
0
8407
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
1
8512
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8612
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7347
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6175
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5638
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4171
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
1969
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1732
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.