Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Forward Declarations

Reply
Thread Tools

Forward Declarations

 
 
ena8t8si@yahoo.com
Guest
Posts: n/a
 
      07-18-2006

Keith Thompson wrote:
> writes:
> > Keith Thompson wrote:
> >> Tom Plunket <> writes:
> >> > 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.

> >
> > Usually the best argument in favor of using a typedef
> > is that the name defined reflects how you want client
> > code to view the type.
> >
> > If client code should view the type as opaque, then
> > using typedef for a struct type makes sense.
> >
> > If client code should view a struct transparently,
> > then no typedef - just use struct.
> >
> > In my programming, I tend to use abstraction rather
> > a lot, so usually types are typedef'ed. But I
> > understand both modes, and use either, as appropriate.
> >
> > There is one typedef idiom that bears mentioning:
> >
> > typedef struct { ... } *Foo;
> >
> > This idiom is useful when the underlying structs
> > should always be malloc'ed, never static or auto.
> > Because of how the type is declared, no code will
> > have these structs other than {m,c,re}alloc()'ed
> > ones.

>
> In that case, it would probably make sense to hide the *alloc() and
> free() calls behind some type-specific functions; the *alloc()
> wrappers could also do any necessary initialization of the struct
> members. This is basically what fopen() and fclose() do, except that
> the pointer isn't hidden behind a typedef; the members of the
> structure are effectively hidden not by the fact that there's no name
> for the structure type (there is, FILE), but by the fact that the
> details are undocumented, and code that depends on them will break
> when ported.


It depends what you want to achieve.

If you want the structure members accessed only
within the implementing module, then something
like

typedef struct __FILE FILE;

in a header, and a subsequent

struct __FILE { ... };

in the implementing module is usually a good way
to do that. (User code shouldn't use the __'s,
other than that it's the same.)

If what you want is to guarantee that struct
instances are made only through *alloc(), then
the idiom

typedef struct { ... } *Foo;

is a way to do that. C gives you a choice,
but it has to be one or the other, it can't
be both.

 
Reply With Quote
 
 
 
 
Michael Wojcik
Guest
Posts: n/a
 
      07-18-2006

In article < om>, writes:
>
> Usually the best argument in favor of using a typedef
> is that the name defined reflects how you want client
> code to view the type.
>
> If client code should view the type as opaque, then
> using typedef for a struct type makes sense.


Perhaps, but since C already contains an idiom for opaque types which
does not require a typedef, the typedef is still superfluous.

When I have a header file that contains:

struct foo;
struct foo *MakeFoo(void);
void UseFoo(struct foo *);

I know I am dealing with an opaque type. No typedef need apply.

What's more, I know that I am dealing with a pointer-to-incomplete-
structure, which is useful if, for example, I want to insert some
temporary instrumentation that tracks the struct-foo objects I have
created; I know I can print some representation of a struct foo *
with the %p format specifier (after casting it to void *), for
example. That's much better than a typedef that hides the fact that
I am dealing with a pointer, which I realize is not what you
suggested, but is all too common among the fans of typedef.

--
Michael Wojcik

Not the author (with K.Ravichandran and T.Rick Fletcher) of "Mode specific
chemistry of HS + N{_2}O(n,1,0) using stimulated Raman excitation".
 
Reply With Quote
 
 
 
 
ena8t8si@yahoo.com
Guest
Posts: n/a
 
      07-19-2006

Michael Wojcik wrote:
> In article < om>, writes:
> >
> > Usually the best argument in favor of using a typedef
> > is that the name defined reflects how you want client
> > code to view the type.
> >
> > If client code should view the type as opaque, then
> > using typedef for a struct type makes sense.

>
> Perhaps, but since C already contains an idiom for opaque types which
> does not require a typedef, the typedef is still superfluous.
>
> When I have a header file that contains:
>
> struct foo;
> struct foo *MakeFoo(void);
> void UseFoo(struct foo *);
>
> I know I am dealing with an opaque type. No typedef need apply.


You're using the term opaque in different
sense than I was. As I was using the term,
opaque means a type that client code should
know nothing about. The "opaque type" that
you suggest requires client code to know
(a) that it's a pointer and (b) that the
pointer points to a struct. That's more
translucent than opaque.

For translucent types, struct foo * is ok.
A type intended to be really opaque should
use typedef.

 
Reply With Quote
 
Michael Wojcik
Guest
Posts: n/a
 
      07-20-2006

In article <. com>, writes:
> Michael Wojcik wrote:
> > In article < om>, writes:
> > >
> > > If client code should view the type as opaque, then
> > > using typedef for a struct type makes sense.

> >
> > Perhaps, but since C already contains an idiom for opaque types which
> > does not require a typedef, the typedef is still superfluous.

>
> You're using the term opaque in different
> sense than I was.


Perhaps I am, but I find the distinction you draw trivial and
superfluous.

> As I was using the term,
> opaque means a type that client code should
> know nothing about.


This cannot be achieved in C. The "client code" can still apply the
sizeof operator to a typedef, for example. Assuming an implementation
with decent QoI, trial code can be written to determine what types the
typedef is compatible with, by observing diagnostics.

> The "opaque type" that
> you suggest requires client code to know
> (a) that it's a pointer and (b) that the
> pointer points to a struct.


So what? In some languages (eg OCaml), essentially all user-defined
types are references to structured types. That doesn't seem to be a
problem for them. I'll be damned if I can think why this would be a
problem in C. What precious information is leaking out of the abstract
interface?

> That's more translucent than opaque.


The size and nature of the contents are invisible outside the
interface. That's as good a definition of "opaque type" as any other
I've seen.

> A type intended to be really opaque should
> use typedef.


You're welcome to that opinion. I don't find it convincing.

I'll also note in passing that using typedefs for "opaque" (abstract)
types encourages not wrapping elementary types in structs. And that,
in turn, may lead to maintenance problems, if the type needs to be
extended later, but existing callers have divined its non-struct
nature (eg by reading headers) and written code that relies on that
fact.

If struct is your only type-abstraction mechanism, this is never an
issue.

--
Michael Wojcik

He smiled and let his gaze fall to hers, so that her cheek began to
glow. Ecstatically she waited until his mouth slowly neared her own.
She knew only one thing: rdoeniadtrgove niardgoverdgovnrdgog.
 
Reply With Quote
 
ena8t8si@yahoo.com
Guest
Posts: n/a
 
      07-22-2006

Michael Wojcik wrote:
> In article <. com>, writes:
> > Michael Wojcik wrote:
> > > In article < om>, writes:
> > > >
> > > > If client code should view the type as opaque, then
> > > > using typedef for a struct type makes sense.
> > >
> > > Perhaps, but since C already contains an idiom for opaque types which
> > > does not require a typedef, the typedef is still superfluous.

> >
> > You're using the term opaque in different
> > sense than I was.

>
> Perhaps I am, but I find the distinction you draw trivial and
> superfluous.


As long as you understand the distinction, you can respond
to what I'm actually saying and not something else.

> > As I was using the term,
> > opaque means a type that client code should
> > know nothing about.

>
> This cannot be achieved in C. The "client code" can still apply the
> sizeof operator to a typedef, for example. Assuming an implementation
> with decent QoI, trial code can be written to determine what types the
> typedef is compatible with, by observing diagnostics.


Would you prefer "a type that client code should know as
little about as possible"?

In any case that's not really the issue. The question is
not whether client code _can_ know something, but whether it
_must_ know something. An opaque type is one where
knowledge of the type's representation should be confined to
the module that supplies/implements it.

> > The "opaque type" that
> > you suggest requires client code to know
> > (a) that it's a pointer and (b) that the
> > pointer points to a struct.

>
> So what? In some languages (eg OCaml), essentially all user-defined
> types are references to structured types. That doesn't seem to be a
> problem for them. I'll be damned if I can think why this would be a
> problem in C. What precious information is leaking out of the abstract
> interface?


If the type is defined with a typedef, essentially no
representation information has to leak out.

If there isn't a typedef, then representation information is
forced to leak out, as explained above.

> > That's more translucent than opaque.

>
> The size and nature of the contents are invisible outside the
> interface. That's as good a definition of "opaque type" as any other
> I've seen.


You seem to want to argue about what makes a good definition
for "opaque type". Either you're missing the point of what
I'm saying, or you're just being deliberately difficult.

> > A type intended to be really opaque should
> > use typedef.

>
> You're welcome to that opinion. I don't find it convincing.


I expect that's because you insist on reading "opaque" in
the sense you want to use it rather than as I have been
using it.

> I'll also note in passing that using typedefs for "opaque" (abstract)
> types encourages not wrapping elementary types in structs. And that,
> in turn, may lead to maintenance problems, if the type needs to be
> extended later, but existing callers have divined its non-struct
> nature (eg by reading headers) and written code that relies on that
> fact.
>
> If struct is your only type-abstraction mechanism, this is never an
> issue.


Your reasoning here starts with a false premise.

 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      07-30-2006
[on opaque types, and "typedef" vs "struct"]

In article < .com>
<> wrote:
>In any case that's not really the issue. The question is
>not whether client code _can_ know something, but whether it
>_must_ know something. An opaque type is one where
>knowledge of the type's representation should be confined to
>the module that supplies/implements it.


Indeed -- but the problem with "typedef" is that, in C, you must
know whether the typedef-name is a synonym for an array type,
because array types do not behave the same as any other type.

Hence, typedef is not at all useful for opaque types in C, unless
you also add a (programmer-imposed) constraint that no typedef ever
names an array type.

If you simply make every opaque type a structure -- no pointer is
required -- you get the desired effect:

struct user_type_0;
struct user_type_1;
struct user_type_2;

All three types are unique and well-behaved, and the client code
need not know anything at all. If we "peek behind the curtain",
we might find, e.g.:

struct user_type_0 { double val; };
struct user_type_1 { double val; };
struct user_type_2 { struct u2_implementation *ptr; };

but all the user knows about them is that each one behaves like
other primitive types in C (of course, one can never apply arithmetic
operators directly, for instance).
--
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.
 
Reply With Quote
 
ena8t8si@yahoo.com
Guest
Posts: n/a
 
      07-31-2006

Chris Torek wrote:
> [on opaque types, and "typedef" vs "struct"]
>
> In article < .com>
> <> wrote:
> >In any case that's not really the issue. The question is
> >not whether client code _can_ know something, but whether it
> >_must_ know something. An opaque type is one where
> >knowledge of the type's representation should be confined to
> >the module that supplies/implements it.

>
> Indeed -- but the problem with "typedef" is that, in C, you must
> know whether the typedef-name is a synonym for an array type,
> because array types do not behave the same as any other type.
>
> Hence, typedef is not at all useful for opaque types in C, unless
> you also add a (programmer-imposed) constraint that no typedef ever
> names an array type.
>
> If you simply make every opaque type a structure -- no pointer is
> required -- you get the desired effect:
>
> struct user_type_0;
> struct user_type_1;
> struct user_type_2;
>
> All three types are unique and well-behaved, and the client code
> need not know anything at all. If we "peek behind the curtain",
> we might find, e.g.:
>
> struct user_type_0 { double val; };
> struct user_type_1 { double val; };
> struct user_type_2 { struct u2_implementation *ptr; };
>
> but all the user knows about them is that each one behaves like
> other primitive types in C (of course, one can never apply arithmetic
> operators directly, for instance).


Your comments don't make sense to me. If I'm defining
an opaque type that needs an array representation, the
type can be defined as an array wrapped in a struct:

typedef struct { whatever_t v[SOME_N]; } opaque;

If I'm defining an opaque type that shouldn't be assigned
or have its value passed directly, but always by address,
the type can be defined wrapping the representation type
in an array:

typedef whatever_t opaque[1];
void assign_opaque( opaque *, opaque * );

...

opaque o1, o2;
assign_opaque( &o1, &o2 ); /* can't do o1 = o2; */

If I'm defining an opaque type that needs to have
some scalar operations exposed (eg, == 0), the type
can be defined in a usual way:

typedef struct some_struct_t *opaque;

...

opaque o1;
if(!o1) ...

If I'm defining an opaque type that's a scalar type
but should _not_ have scalar operations exposed, the
type can be wrapped in a struct:

typedef struct { scalar_t v; } opaque;

And finally, if I'm defining an opaque type that's
a scalar type that shouldn't be assigned and also
shouldn't be accidentally turned into a pointer to
its scalar representation, the type can be wrapped
in struct wrapped in an array:

typedef struct { scalar_t v; } opaque[1];

In all of these cases the client code uses just the
name that was typedef'ed. Using typedef is more
flexible than always using struct, not less flexible.

 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      07-31-2006
In article < .com>,
<> wrote:
>f I'm defining an opaque type that shouldn't be assigned
>or have its value passed directly, but always by address,
>the type can be defined wrapping the representation type
>in an array:
>
> typedef whatever_t opaque[1];
> void assign_opaque( opaque *, opaque * );


This argument did occur to me later today (while at the gym),
and is one in favor of typedef with nothing *but* arrays, since
using any other type allows ordinary assignment:

T a, b;
...
b = a; /* error if T is an alias for an array type */

which is in fact letting information (namely, "simple assigmnent
is OK") leak out of the abstraction. But C confounds this, at
least to some extent:

void f(T a, T b) {
...
b = a; /* oops, succeeds after all */
...
}

through the "array rewritten as pointer" rule for parameters.

(This is the sort of problem I mean to indict, regarding arrays:
their "array-ness" leaks out in ways one does not always intend.
Again, this particular problem can be avoided through programmer
discipline; but if you are going to call upon discipline, you can
simply dispense with opaque types in the first place. )

(As a side comment, a lot of my instincts here were set back in
the Bad Old Days when "&array" was diagnosed, instead of producing
a pointer to the entire array.)
--
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.
 
Reply With Quote
 
ena8t8si@yahoo.com
Guest
Posts: n/a
 
      08-01-2006

Chris Torek wrote:
> In article < .com>,
> <> wrote:
> >f I'm defining an opaque type that shouldn't be assigned
> >or have its value passed directly, but always by address,
> >the type can be defined wrapping the representation type
> >in an array:
> >
> > typedef whatever_t opaque[1];
> > void assign_opaque( opaque *, opaque * );

>
> This argument did occur to me later today (while at the gym),
> and is one in favor of typedef with nothing *but* arrays, since
> using any other type allows ordinary assignment:
>
> T a, b;
> ...
> b = a; /* error if T is an alias for an array type */
>
> which is in fact letting information (namely, "simple assigmnent
> is OK") leak out of the abstraction. But C confounds this, at
> least to some extent:
>
> void f(T a, T b) {
> ...
> b = a; /* oops, succeeds after all */
> ...
> }
>
> through the "array rewritten as pointer" rule for parameters.


Excellent point. No good way around this problem that I can
see.

> (This is the sort of problem I mean to indict, regarding arrays:
> their "array-ness" leaks out in ways one does not always intend.
> Again, this particular problem can be avoided through programmer
> discipline; but if you are going to call upon discipline, you can
> simply dispense with opaque types in the first place. )


I don't think of it as an either/or situation. Many (most?)
programming techniques benefit from both discipline and some
level of automated support. A combination of the two is
usually better than either individually.

Furthermore, much of the motivation (as I see it) for using
opaque types is to protect against a change in representation.
If a typedef is used in such cases, then it's easier to switch
between the different scenarios given in my previous message.
Using some struct type as the declaring type limits some options.
Of course, sometimes limiting those options is just what you
want, and in cases like that using struct is a better expression
of the intent. In most cases though I usually want to preserve
as much representation flexibility as I can.

> (As a side comment, a lot of my instincts here were set back in
> the Bad Old Days when "&array" was diagnosed, instead of producing
> a pointer to the entire array.)


Of course I'm guessing, but I conjecture that a difference
in our respective backgrounds could account for a lot of
the difference in our viewpoints. I was already very well
grounded in abstract data types and information hiding by
the time I started programming in C; using typedef to define
abstract/opaque types is something I did probably literally
on day one of my C programming experience.

None of which is meant to say anything negative about anyone with
a different background. I enjoy and benefit from the comments
that come out of your experience and background.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
forward declarations and namespaces? Steven T. Hatton C++ 6 05-05-2004 01:26 PM
NEED HELP with forward declarations Alan Lee C++ 5 04-05-2004 01:03 PM
Forward declarations and namespaces whithers C++ 4 01-16-2004 07:12 AM
Some problems with forward declarations mjm C++ 3 08-13-2003 12:48 AM
namespaces and forward declarations matthew polder C++ 1 07-24-2003 04:06 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57