Typedef structs

S

stephen henry

Hi all,

I have a question that I'm having difficulty answering. If I have a
struct:

typedef struct my_struct_tag{

struct my_other_struct *other;

} my_struct_tag

(I'm using the struct when declaring other because the definition of
my_other_struct is in another source file.)

Then, I want to access, from a different source file,

my_struct *tmp;
my_other_struct *other_struct;

tmp->other = other_struct;

But, for me, this gives a warning saying that the assignment assigns
different pointer types. If I change the code to:

tmp->other = (struct my_other_struct *)other_struct;

It works, but this is fugly. Is there anyway to assign like the first
method (ie without the cast).

Thanks,

Stephen Henry
 
M

Michael Mair

Hi,


I am not sure whether I understand your problem;
if I do
> cat os.h
struct os {int c;};
> cat s.h
typedef struct s {struct os *optr;} s_t;
> cat test.c
#include "s.h"
#include "os.h"

int main (void)
{
s_t S, *pS;
struct os OS, *pOS;

pOS = &OS;
pS = &S;
pS->optr = pOS;

return 0;
}

then test.c compiles even without warning, irrespective
of the order of the #includes or the fact whether I use
s or s_t for the typedef. (gcc -Wall -ansi -pedantic test.c)

How does you setup differ from the above?


Cheers,
Michael
 
E

Eric Sosman

stephen said:
Hi all,

I have a question that I'm having difficulty answering. If I have a
struct:

typedef struct my_struct_tag{

struct my_other_struct *other;

} my_struct_tag

(I'm using the struct when declaring other because the definition of
my_other_struct is in another source file.)

Then, I want to access, from a different source file,

my_struct *tmp;
my_other_struct *other_struct;

tmp->other = other_struct;

But, for me, this gives a warning saying that the assignment assigns
different pointer types. If I change the code to:

tmp->other = (struct my_other_struct *)other_struct;

It works, but this is fugly. Is there anyway to assign like the first
method (ie without the cast).

In some times and places, Royalty were considered to
be semi-divine, out of the general run of mankind (no doubt
the Royals encouraged this notion). Since it would be an
unthinkable sacrilege for a mere commoner to lay hands upon
the Royal person, some difficulty arose when there was
sickness or injury at the palace: How could the skilled
medicine man or barber-surgeon conduct a physical examination
of the ailing ruler without touching him?

The solution was to use a stand-in. The untouchable
Majesty would describe his symptoms to a common companion,
and the companion would submit to the specialist's examination
while doing his best to imitate his King's complaint. Given
the state of the medical arts and sciences of the time this
curious practice may not have made much practical difference
in the outcome, but today's doctors and nurses might be just
a wee bit hampered by such a roundabout and indirect custom,
don't you think?

The point of this story is that the pseudo-code you've
shown is just like the stand-in commoner. Is there something
untouchably holy about your actual code that prevents you from
revealing it to our unwashed gaze? Personally, I find it
surpassingly difficult to diagnose your problem when all I get
to see is your proxy. Please post a *complete* and *minimal*
example of *actual* code.

"A King of autocratic power We,
A despot whose tyrannic will is law,
Whose rule is paramount o'er land and sea,
A Presence of unutterable awe!
But though the awe that I inspire
Must shrivel with imperial fire
All foes whom it may chance to touch,
To judge by what I see and hear,
It does not seem to interfere
With popular enjoyment, much."

-- Paramount, Rex
 
X

xarax

stephen henry said:
Hi all,

I have a question that I'm having difficulty answering. If I have a
struct:

typedef struct my_struct_tag{

struct my_other_struct *other;

} my_struct_tag

(I'm using the struct when declaring other because the definition of
my_other_struct is in another source file.)

Then, I want to access, from a different source file,

my_struct *tmp;
my_other_struct *other_struct;

You probably want that line to say:

struct my_other_struct *other_struct;
^^^^^^

That is, you forgot the "struct" keyword.
tmp->other = other_struct;

But, for me, this gives a warning saying that the assignment assigns
different pointer types. If I change the code to:

tmp->other = (struct my_other_struct *)other_struct;

It works, but this is fugly. Is there anyway to assign like the first
method (ie without the cast).

Thanks,

Stephen Henry


--
----------------------------
Jeffrey D. Smith
Farsight Systems Corporation
24 BURLINGTON DRIVE
LONGMONT, CO 80501-6906
http://www.farsight-systems.com
z/Debug debugs your Systems/C programs running on IBM z/OS for FREE!
 
C

ChokSheak Lau

write a "typedef struct my_other_struct *my_other_struct_ptr;"
before you declare the code typedef struct my_struct_tag { ...} ...;

this is doubly-independent definition. C actually allows typedef of a
struct pointer (pointer only) without knowing the definition.

chok
 
S

stephen henry

xarax said:
You probably want that line to say:

struct my_other_struct *other_struct;
^^^^^^

That is, you forgot the "struct" keyword.

Sorry, but I need to clarify somewhat:

Say I have two structures in two seperate files

file1.c
-------

typedef struct my_structure1_tag {

// FOO;

} my_structure1;

file2.c
-------

typedef struct my_structure2_tag {

my_structure1 *my_struct;

} my_structure2;

Now, in order to get file2.c to compile I have to change it so that it
reads:

typedef struct my_structure2_tag {

STRUCT my_structure1 *my_struct;

} my_structure2;

Without the STRUCT i would get a syntax error because the compiler has
not compiled file1.c (which contains the decleration of
my_structure1). By inserting STRUCT I'm essentially saying to the
compiler that my_struct is a pointer to a structure, but I've not yet
defined what that structure actually is yet. What I would like to do,
would be to assigned a newly created my_structure1 as follows:

my_structure1 *structure1;
my_structure2 *structure2;

structure1->my_struct = structure2;

However, because in structure2, my_struct is declares as STRUCT
my_structure1 I have to cast the above assignment to:

structure1->my_struct = (struct my_structure1 *)structure2;

If I don't do this cast, I would get an error saying that I'm
assigning two incompatible pointer types.

So the question is: Is there anyway to compile C such that a structure
can contain another -I believe its called an incomplete- structure
from another, not yet compiled file, without having to cast in the
above manner.

Thanks,

Stephen Henry
 
M

Michael Mair

Hiho,
file1.c
-------

typedef struct my_structure1_tag {

// FOO;

} my_structure1;

--> file1.h
file2.c
------- #include "file1.h"

typedef struct my_structure2_tag {

my_structure1 *my_struct;
without the #include, this type is not known.
} my_structure2;

Now, in order to get file2.c to compile I have to change it so that it
reads:

typedef struct my_structure2_tag {

STRUCT my_structure1 *my_struct;
with the #include, both ways are possible; this shoul
read struct. If you want to mark something, use a comment.
} my_structure2;

it would be better, to put that typedef into file2.h (which
includes file1.h).
Without the STRUCT i would get a syntax error because the compiler has
not compiled file1.c (which contains the decleration of
my_structure1). By inserting STRUCT I'm essentially saying to the
compiler that my_struct is a pointer to a structure, but I've not yet
defined what that structure actually is yet. What I would like to do,
would be to assigned a newly created my_structure1 as follows:

my_structure1 *structure1;
my_structure2 *structure2;

structure1->my_struct = structure2;

That is not possible. structure1 only contains // FOO;
However, because in structure2, my_struct is declares as STRUCT
my_structure1 I have to cast the above assignment to:

structure1->my_struct = (struct my_structure1 *)structure2;

If I don't do this cast, I would get an error saying that I'm
assigning two incompatible pointer types.

In which file are you doing this, file1.c, file2.c, or some
yet unknown file3.c?
So the question is: Is there anyway to compile C such that a structure
can contain another -I believe its called an incomplete- structure
from another, not yet compiled file, without having to cast in the
above manner.

If I understand you correctly, try whether
struct mystructure1;

typedef struct my_structure2_tag {
struct my_structure1 *my_struct;
} my_structure2;
helps you.


You have been asked -- directly and indirectly -- to post
a minimal example. Please do not use Pseudo-Code, as this is
likely to produce more confusion than clarifying; apart from
that, yours is broken.

Some notes:
- Use header files for your types, #defines, prototypes and so on.

- Take the time to bring the example down to a minimal example
you can post here (c.f. my first answer to your question).

- Do not tell us what you think happens but give us actual code.
 
M

Michael Mair

Hiho,
> file1.c
> -------
>
> typedef struct my_structure1_tag {
>
> // FOO;
>
> } my_structure1;

--> file1.h
>
> file2.c
> ------- #include "file1.h"
>
> typedef struct my_structure2_tag {
>
> my_structure1 *my_struct;
without the #include, this type is not known.
>
> } my_structure2;
>
> Now, in order to get file2.c to compile I have to change it so that it
> reads:
>
> typedef struct my_structure2_tag {
>
> STRUCT my_structure1 *my_struct;
with the #include, both ways are possible; this shoul
read struct. If you want to mark something, use a comment.
>
> } my_structure2;

it would be better, to put that typedef into file2.h (which
includes file1.h).
>
> Without the STRUCT i would get a syntax error because the compiler has
> not compiled file1.c (which contains the decleration of
> my_structure1). By inserting STRUCT I'm essentially saying to the
> compiler that my_struct is a pointer to a structure, but I've not yet
> defined what that structure actually is yet. What I would like to do,
> would be to assigned a newly created my_structure1 as follows:
>
> my_structure1 *structure1;
> my_structure2 *structure2;
>
> structure1->my_struct = structure2;

That is not possible. structure1 only contains // FOO;
> However, because in structure2, my_struct is declares as STRUCT
> my_structure1 I have to cast the above assignment to:
>
> structure1->my_struct = (struct my_structure1 *)structure2;
>
> If I don't do this cast, I would get an error saying that I'm
> assigning two incompatible pointer types.

In which file are you doing this, file1.c, file2.c, or some
yet unknown file3.c?
> So the question is: Is there anyway to compile C such that a structure
> can contain another -I believe its called an incomplete- structure
> from another, not yet compiled file, without having to cast in the
> above manner.

If I understand you correctly, try whether
struct mystructure1;

typedef struct my_structure2_tag {
struct my_structure1 *my_struct;
} my_structure2;
(untested) helps you.


You have been asked -- directly and indirectly -- to post
a minimal example. Please do not use Pseudo-Code, as this is
likely to produce more confusion than clarifying; apart from
that, yours is broken.

Some notes:
- Use header files for your types, #defines, prototypes and so on.

- Take the time to bring the example down to a minimal example
you can post here (c.f. my first answer to your question).

- Do not tell us what you think happens but give us actual code.
 
C

Chris Torek

Sorry, but I need to clarify somewhat:

[more sample code that is definitely not the actual code]

Suppose you were a car mechanic and I drove up in a vehicle and
said "my car isn't working right; it won't start." You might wonder
how I got the car to you. What would you think if I told you: "Oh,
this isn't my car, this is my neighbor's car, but we have the same
brand of vehicle. You should be able to fix mine by looking at
his, right?"

:)

In any case, I have a method I recommend. Stop using typedef for
structs.

Just plain stop using it. You do not NEED it, and what it does is
rarely what most beginning or even intermediate-level C programmers
expect. Use structure tags, and most of your problems will go
away.
 
T

Tim Rentsch

Chris Torek said:
In any case, I have a method I recommend. Stop using typedef for
structs.

Just plain stop using it. You do not NEED it, and what it does is
rarely what most beginning or even intermediate-level C programmers
expect. Use structure tags, and most of your problems will go
away.

Usually I find myself in agreement with Chris Torek's advice;
in this case however I think the advice given is somewhat
shortsighted.

Right from the very beginning, C programmers should be taught
to follow the pattern


typedef struct some_type_name_struct_tag some_type_name;


struct some_type_name_struct_tag {

/* ... definition goes here ... */

};


and elsewhere always use 'some_type_name' to refer to the structure
type.

I don't mean to suggest that they follow the pattern blindly; there
should be explanation of the two pieces. But the amount of
explanation needed isn't that much, and the development practice is a
good one to be in the habit of following. Surely at some point there
will also be a need to explain about 'struct' tags and their separate
namespace, and so forth, but the pattern above is helpful much more
often than it's harmful - it's better to learn it earlier rather than
later.
 
P

pete

Tim said:
Usually I find myself in agreement with Chris Torek's advice;
in this case however I think the advice given is somewhat
shortsighted.

Right from the very beginning, C programmers should be taught
to follow the pattern

typedef struct some_type_name_struct_tag some_type_name;

struct some_type_name_struct_tag {

/* ... definition goes here ... */

};

and elsewhere always use 'some_type_name' to refer to the structure
type.

I don't mean to suggest that they follow the pattern blindly; there
should be explanation of the two pieces. But the amount of
explanation needed isn't that much, and the development practice is a
good one to be in the habit of following. Surely at some point there
will also be a need to explain about 'struct' tags and their separate
namespace, and so forth, but the pattern above is helpful much more
often than it's harmful - it's better to learn it earlier rather than
later.

Your explanation is missing the part about why it's good
to typedef a struct. I don't see any point in doing it.
Why is
some_type_name object;
superior to
struct some_type_name_struct_tag object;
?
 
C

Chris Torek

This is what I recommend as an alternative *if* one is stubbornly
insistent on using typedefs.

And indeed, in the past, I have done that (feel free to DejaGoogle
search for such articles). Sometimes I have less time to post,
though. :)

Your explanation is missing the part about why it's good
to typedef a struct. I don't see any point in doing it.
Why is
some_type_name object;
superior to
struct some_type_name_struct_tag object;
?

I do not believe it is, myself, but I acknowledge that this is a
matter of opinion rather than fact.
 
T

Tim Rentsch

pete said:
Tim Rentsch wrote:

Your explanation is missing the part about why it's good
to typedef a struct. I don't see any point in doing it.
Why is
some_type_name object;
superior to
struct some_type_name_struct_tag object;
?

Ahh, this is a good question. I would offer several reasons:

1. (minor) Slight economy of expression - shorter to omit 'struct'.

2. Using a typedef'ed name gives greater flexibility in the choice
of type - if later we want some_type_name to be a 'union' or 'int'
or 'enum', less of the program will need to change as a result.

3. Greater safety - if the type is defined in a header file (as it
very likely may be), and the header file is not #include'ed, using

some_type_name *x;

will produce an error, whereas

struct some_type_name_struct_tag *x;

need no produce any diagnostic at all. Sometimes the second case is
perfectly easy to figure out, but the first case is *always* easy to
figure out.

4. Natural extension to opaque types - a commonly useful pattern is to
pass pointers where the pointer type is public but the type being
pointed at is private; if someone is used to separate definitions for
the type name and the 'struct' members, that leap will seem more
natural than if they aren't - just move the typedef to a public header
file and keep the struct definition local. In a sense this point is
similar to point (2), but there is also something else - for didactic
reasons we would like to be able introduce opaque types early in the
educational cycle, and having separately defined type names makes it
easier both to make use of opaque (pointer) types and to explain some
mechanics about how to express opaque types in C.

In connection with point 4, for a type that is opaque and will always
be accessed via pointers, there is nothing wrong with defining a
pointer type rather than an instance type as the defined type name.
(Of course it's important to get the conventions right so which is
which is always clear.)


Forgive me for not listing these earlier - I'd sort of assumed without
thinking about it that most long time C developers would be aware of
all of these already.
 
T

Tim Rentsch

Chris Torek said:
I do not believe it is, myself, but I acknowledge that this is a
matter of opinion rather than fact.

To be fair here, I should say that in addition to some advantages that
the first form has (which I posted separately), there also are some
advantages to the second form. I think everyone would agree that
there are some advantages to each approach; where opinions might
differ is on the relative merits of the two sets of advantages. My
other posting didn't try to address either the advantages of the
second form or the question of the relative merits of the two
approaches.
 
K

Keith Thompson

Tim Rentsch said:
Right from the very beginning, C programmers should be taught
to follow the pattern


typedef struct some_type_name_struct_tag some_type_name;


struct some_type_name_struct_tag {

/* ... definition goes here ... */

};


and elsewhere always use 'some_type_name' to refer to the structure
type.

The counterargument is that it hides (or attempts to hide) information
that shouldn't be hidden.

Assigning a simple name to a complicated type can be useful if the
goal is data abstraction. It can encourage the programmer to focus on
the operations that are appropriate to the type, without worrying
about the lower level operations that may not be. An example of this
is size_t; the name doesn't tell you whether it's signed, unsigned, or
floating-point, and the programmer shouldn't write code that depends
on such details.

For a struct type, however, there's often not much you can do with the
type without knowing that it's a struct. If you're going to refer to
members, you obviously *have* to know that it's a struct. (The type
FILE in <stdio.h> is an exception to this; the user of the interface
can use it only via pointers, and there are no portably defined
members.)

A good rule of thumb is probably:

If you can sensibly hide from the user the fact that a type is a
struct, use a typedef (such as FILE in <stdio.h>). If not, don't, and
let the user refer to the type as "struct foo" (such as struct tm in
<time.h>). The latter is probably more common.

(Personally, I'm not as opposed to gratuitous typedefs for structs as
some people are, but I understand the arguments.)
 
P

pete

Keith said:
Assigning a simple name to a complicated type can be useful if the
goal is data abstraction. It can encourage the programmer to focus on
the operations that are appropriate to the type, without worrying
about the lower level operations that may not be. An example of this
is size_t; the name doesn't tell you whether it's signed, unsigned, or
floating-point, and the programmer shouldn't write code that depends
on such details.

The programmer can depend on size_t being an unsigned integer type.
 
K

Keith Thompson

pete said:
The programmer can depend on size_t being an unsigned integer type.

Sorry, that was a braino. I meant time_t, not size_t.

But that raises a good point. C's type system isn't as expressive as
it could be (which is not to say that it *should* be as expressive as
it could be). You can have a type name that doesn't tell you anything
about a type (foo_t), or one that tells you only that it's a struct
(struct foo), but there's no syntax for specifying that time_t is an
arithmetic type, or that size_t is an unsigned integer type without
saying which one. In many cases, you have to depend on documentation
to let the programmer know what properties can be depended on.

Any convention about whether to use "struct foo" or a typedef is going
to be an imperfect compromise.
 
B

Ben Pfaff

pete said:
Your explanation is missing the part about why it's good
to typedef a struct. I don't see any point in doing it.
Why is
some_type_name object;
superior to
struct some_type_name_struct_tag object;

I generally do not typedef structs. However, occasionally I run
into an awkward situation where I want one struct to be
interchangeable for another. For example, suppose one already
has a linked list whose element is a `struct list_elem'. If one
then wishes to implement a hash table with chaining it would be
convenient for abstraction purposes to declare `struct hash_elem'
as an alias for `struct list_elem'. Unfortunately, this simply
cannot be done in C. `#define hash_elem list_elem' is not
acceptable because it pollutes the global namespace, not just the
tag namespace. A `typedef' is a reasonable way out.
 
T

Tim Rentsch

Keith Thompson said:
The counterargument is that it hides (or attempts to hide) information
that shouldn't be hidden.
^^^^^^^^^
What reasons would you offer that it shouldn't be hidden? In a separate
article I responded to another poster's query and listed some advantages
of the separate type name approach. Could one of the just-use-structs
advocates respond and list some principal advantages of not using
a separate type name?

Assigning a simple name to a complicated type can be useful if the
goal is data abstraction.

More importantly, information hiding. See the well-known papers
by David Parnas. Also Brooks's "Mythical Man Month", 20th Anniversary
Edition.

For a struct type, however, there's often not much you can do with the
type without knowing that it's a struct. [...]

Here's a list of things that can be done with (most) complete types,
without knowing what type they are:

1. Declare variables of the type (and arrays-of and pointers-to same)
2. Assign values (and accept parameters and return results)
3. Pass values to functions, and get values back as results
4. Take the address with '&'
5. Use 'sizeof' to get the size, which allows allocation with 'malloc()'

In C99 that might be all complete object types - I'm unsure about the status
in C99 of array assignment. Note that the list is more than enough to allow
useful work to get done, as the 'FILE' example demonstrates.

A good rule of thumb is probably:

[...]

Let me suggest this rule: Always use typedefs for structs, except in
cases where the advantages of not using them outweigh the advantages
of using them. I've yet to see a statement in this thread about what
the advantages of not using typedefs for structs are, let alone a
comparison of the different advantages for the two approaches.

(Personally, I'm not as opposed to gratuitous typedefs for structs as
some people are, but I understand the arguments.)

Keith, I'm disappointed. This kind of rhetoric - a content-free
statement giving a "non-argument" argument, including the emotional
hook word "gratuitous" - should be below you.
 

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

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top