struct and typedef problems

B

burn

Hello,
i am writing a program under linux in c and compile my code with make
and gcc.

Now i have 4 files: init.c/h and packets.c/h. Each header-file contains
some:

init.h:
struct xyz
{
int a;
};
typedef struct xyz XYZ;

void fkt_1(XYZ *, ABC *);

packets.h:
struct abc
{
int b;
}
typedef struct abc ABC;

void fkt_2(XYZ *, ABC *);

Because one file is compiling before the other this one does not know
the structure from the other and i get an parser error before, let's
say, ABC.

I did some research in this newsgroup and in the internet, tried to use
"extern struct abc" or something like that but nothing worked.

Can anybody tell me what is wrong and how to fix it?

Many thanks

björn
 
P

pete

burn said:
Hello,
i am writing a program under linux in c and compile my code with make
and gcc.

Now i have 4 files: init.c/h and packets.c/h. Each header-file contains
some:

init.h:
struct xyz
{
int a;
};
typedef struct xyz XYZ;

void fkt_1(XYZ *, ABC *);

packets.h:
struct abc
{
int b;
}
typedef struct abc ABC;

void fkt_2(XYZ *, ABC *);

Because one file is compiling before the other this one does not know
the structure from the other and i get an parser error before, let's
say, ABC.

I did some research in this newsgroup and in the internet, tried to use
"extern struct abc" or something like that but nothing worked.

Can anybody tell me what is wrong and how to fix it?

This will work,
if the macros haven't already been defined for something else:

/* BEGIN init.h */

#ifndef H_INIT
#define H_INIT

#include "packets.h"

struct xyz {
int a;
};

typedef struct xyz XYZ;

void fkt_1(XYZ *, ABC *);

#endif

/* END init.h */


/* BEGIN packets.h */

#ifndef H_PACKETS
#define H_PACKETS

#include "init.h"

struct abc {
int b;
};

typedef struct abc ABC;

void fkt_2(XYZ *, ABC *);

void fkt_1(XYZ *, ABC *);

#endif

/* END packets.h */

There's a good chance that these two files might be better off
combined as one.
 
C

clayne

Unfortunately - the entire thing is an indicator of bad planning.

If the two modules are sharing a common interface - then it's best to
have them share a common header file to that interface and types used
within that interface.
 
B

burn

thank you for the prompt reply. you both are right, i should probably
restructure my code.

the problem is that i have multiple files doing multiple things on the
same kind of structures - but i think a little bit of thinking should
get that straight ;-)
 
S

Stephen Sprunk

burn said:
thank you for the prompt reply. you both are right, i should probably
restructure my code.

the problem is that i have multiple files doing multiple things on the
same kind of structures - but i think a little bit of thinking should
get that straight ;-)

A common solution is to put all type definitions in types.h and have all
..c files #include "types.h".

<OT>
If you're using a Makefile, be sure to add types.h as a dependency for
all the files that #include it, or your files won't be rebuilt properly
when you make changes to it.
</OT>

S
 
D

Default User

Unfortunately - the entire thing is an indicator of bad planning.


Please quote a relevant portion of the previous message when replying.
To do so from the Google interface, don't use the Reply at the bottom
of the message. Instead, click "show options" and use the Reply shown
in the expanded headers.

Brian
 
D

Default User

burn said:
thank you for the prompt reply. you both are right, i should probably
restructure my code.


Please quote a relevant portion of the previous message when replying.
To do so from the Google interface, don't use the Reply at the bottom
of the message. Instead, click "show options" and use the Reply shown
in the expanded headers.

Brian
 
C

CBFalconer

burn said:
Now i have 4 files: init.c/h and packets.c/h. Each header-file
contains some:
*** edited for minimum vertical space ***
init.h:
struct xyz { int a; };
typedef struct xyz XYZ;
void fkt_1(XYZ *, ABC *);

packets.h:
struct abc { int b; }
typedef struct abc ABC;
void fkt_2(XYZ *, ABC *);

Because one file is compiling before the other this one does
not know the structure from the other and i get an parser error
before, let's say, ABC.

I did some research in this newsgroup and in the internet,
tried to use "extern struct abc" or something like that but
nothing worked.

Can anybody tell me what is wrong and how to fix it?

Forget about .h files for now and concentrate on the needs of the
..c files. First, what is in each .c file that the other .c file
needs to know? That is what goes in the .h file. Its purpose is
to export facts to whatever needs to know about them.

Now you can also use a partial definition of a structure pointer,
until such time as it has to be dereferenced. You can do this
because all pointers to structs occupy the same space and have the
same alignment requirements. Possibly the easiest way is:

/* init.h */
#ifndef H_init_h
#define H_init_h
#include "packets.h"
.... stuff ...
#endif

and the same for packets.h with the init<-->packet ids
interchanged. Then each .c file only has to #include one .h file.
There are negatives to this.

The point to remember is that .h files export things, and they
never define data nor functions, although they may declare them.
 
S

Sarath

Hi,

I think there is no need to combine these two files.
There is a keyword "extern" in C language which tells the compiler that
those functions or variables which are declared with extern are defined
in another file .

So u have to include the other file into this file and declare the
structure in the other file with extern keyword.

I hope this will be of great help for u.

http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

Sarath.B
IIIT-H
India.
 
K

Keith Thompson

Sarath said:
I think there is no need to combine these two files.
There is a keyword "extern" in C language which tells the compiler that
those functions or variables which are declared with extern are defined
in another file .

So u have to include the other file into this file and declare the
structure in the other file with extern keyword.

I hope this will be of great help for u.

http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html

Sarath, I have a couple of requests (things that you should already
have run across if you've been following this newsgroup).

Please provide some context when posting a followup. It's difficult
to tell what "these to files" refers to. It's seldom necessary to
quote the entire article, just enough to make it possible to
understand the followup without seeing the parent article (which may
not be easily available).

To quote CBFalconer's sig quote (in which he quotes me):

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Second, please don't use abbreviations like "u" for "you", "ur" for
"your", and "r" for "are". I'm sure they're perfectly legible if
you're accustomed to them, but most of us aren't. (I understand
they're particularly difficult for many people whose first language is
not English.)

Thanks.
 
L

Lawrence Kirby

Hi,

I think there is no need to combine these two files.
There is a keyword "extern" in C language which tells the compiler that
those functions or variables which are declared with extern are defined
in another file .

The OP mentioned that he trued extern. However that's not appropriate here
since the problem involves types, not objects or functions, and types have
no linkage. So what happens in one file has no bearing
on what happens in anothger, separately compiled file. That's a key
purpose of headers, having the same definitions available in separately
compiled parts of the program.
So u have to include the other file into this file and declare the
structure in the other file with extern keyword.

The extern keyword is not applicable to type declarations, just functions
and objects.

Lawrence
 
C

CBFalconer

Keith said:
.... snip ...

Second, please don't use abbreviations like "u" for "you", "ur"
for "your", and "r" for "are". I'm sure they're perfectly
legible if you're accustomed to them, but most of us aren't.
(I understand they're particularly difficult for many people
whose first language is not English.)

And particularly annoying to those whose first language is
English. To a non-English speaker, whose doesn't have the clue of
pronounciation and to whom English is a written only language,
those abbreviations are totally useless.
 
S

Sarath

Keith said:
Sarath, I have a couple of requests (things that you should already
have run across if you've been following this newsgroup).

Please provide some context when posting a followup. It's difficult
to tell what "these to files" refers to. It's seldom necessary to
quote the entire article, just enough to make it possible to
understand the followup without seeing the parent article (which may
not be easily available).

To quote CBFalconer's sig quote (in which he quotes me):

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Second, please don't use abbreviations like "u" for "you", "ur" for
"your", and "r" for "are". I'm sure they're perfectly legible if
you're accustomed to them, but most of us aren't. (I understand
they're particularly difficult for many people whose first language is
not English.)

Thanks.
Thanks a lot for your suggestions.
Sarath.B
IIIT-H
 
S

Sarath

Keith said:
Sarath, I have a couple of requests (things that you should already
have run across if you've been following this newsgroup).

Please provide some context when posting a followup. It's difficult
to tell what "these to files" refers to. It's seldom necessary to
quote the entire article, just enough to make it possible to
understand the followup without seeing the parent article (which may
not be easily available).

To quote CBFalconer's sig quote (in which he quotes me):

If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.

Second, please don't use abbreviations like "u" for "you", "ur" for
"your", and "r" for "are". I'm sure they're perfectly legible if
you're accustomed to them, but most of us aren't. (I understand
they're particularly difficult for many people whose first language is
not English.)

Thanks.
Thanks a lot for your suggestions.
Sarath.B
IIIT-H
 
K

Keith Thompson

Sarath said:
Keith Thompson wrote: [snip]
Thanks a lot for your suggestions.

You're welcome. And as long as you're open to suggestions:

Your most recent followup was posted twice, about 2 or 3 minutes
apart.

Your original text should generally be left-justified, not indented.
 
D

Dave Thompson

burn wrote:

This will work,
if the macros haven't already been defined for something else:
<snip same plus header guards and cross-#include's,
and declaration of fkt_2 duplicated in packets.h>

Header guards solve the problem of multiple (typically implicit)
inclusion; they do nothing for inter-type dependency.

Aside from combining into a single .h, which depending on your design
may be preferable or at least conveniently acceptable, what you can do
is add a 'forward' declaration of the tag. Three ways:

In each depending file, just the tag:
----- init.h
/* add guards preferably, cross-include if you want to relieve user */
struct xyz { body }; typedef struct xyz XYZ;
/* or combine these as typedef struct xyz { body } XYZ; */
struct abc; /* tag only */ /* must be before any use in prototype */
void fkt_1 (XYZ *, struct abc *);
/* or (struct xyz *, struct abc *) to be consistent */
----- packet.h
/* ditto */
struct abc { body }; typedef struct abc ABC; /* ditto */
struct xyz; /* ditto */
void fkt_2 (struct xyz *, ABC *);
/* or (struct xyz *, struct abc *) to be consistent */

In each depending file also the typedef, but you must guard these
individually or at least separately, because you can have a or even
multiple forward declarations of a tag in addition to the full
declaration, but you cannot redeclare a typedef in C; in C++ you can
as long as the redefinition is effectively identical:
----- init.h
/* guard and cross-include similarly */
typedef struct xyz { body } XYZ; /* as above */
#ifndef T_ABC /* guard for typedef(s) */
#define T_ABC
typedef struct abc ABC;
#endif
void fkt_1 (ABC *, XYZ *);
----- packet.h
/* ditto */
typedef struct abc { body } ABC; /* ditto */
#ifndef T_XYZ /* ditto */
#define T_XYZ
typedef struct xyz XYZ;
#endif
void fkt_2 (XYZ *, ABC *);

Move the typedefs or tags only to a separate file, a la C++ <iosfwd>:
----- typenames.h
typedef struct xyz XYZ;
typedef struct abc ABC;
----- init.h
#include "typenames.h"
struct xyz { body }; /* only, no typedef */
void fkt_1 (ABC *, XYZ *);
----- packet.h
#include "typenames.h"
struct abc { body }; /* ditto */
void fkt_2 (XYZ *, ABC *);

BTW, you can use the same identifier for the struct tag and the
typedef name if you want; you don't need to use lowercase and
uppercase or similar schemes. And except for M$ -- admittedly a big
exception -- it isn't common in C to use all-caps for typedef names.
But these are only(?) style issues.

- David.Thompson1 at worldnet.att.net
 
M

Me

Because one file is compiling before the other this one does not know
the structure from the other and i get an parser error before, let's
say, ABC.

I did some research in this newsgroup and in the internet, tried to use
"extern struct abc" or something like that but nothing worked.

extern is about external definitions.
Can anybody tell me what is wrong and how to fix it?

You were looking for something called "forward declaration":

typedef struct foo {
int a;
} foo;

void fn(foo *, boo *);

What you should do here is somewhere above the fn function, declare an
incomplete boo struct like:

struct boo;
typedef struct boo boo;
// typedef here is optional, but very convenient

or simply just:

typedef struct boo boo;

And it will work. The bad thing about C is that it doesn't allow
duplicate typedefs like C++ does, so you will need an inclusion
mechanism of some sort for typedefs here. The other posters have a
point about just putting everything in a common header file because if
you include foo.h, you should expect that it includes everything you
need to have it work instead of also forcing the programmer to include
boo.h as well. But the forward declaration trick is very useful for
information hiding and reducing compile times (among other things), so
you should keep it in your toolbox.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top