468,771 Members | 1,637 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,771 developers. It's quick & easy.

opaque style question

Hi NG,

I've read some time ago in this NG, that when you're writing a library
it can be good practice to use an opaque type to point to your
structures if the user doesn't need to modify the structure himself.
This way the internal structure of the lib can be changed, and the lib
can be recompiled, but the application using the lib doesn't need to be
recompiled.

But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. I also read somewhere that it's bad
practice to make a typedef to a pointer in such a way that it is not
obvious from looking at the type, in this case lib_t, that it is a
pointer to whatever. So that would mean it would be best to use the
first typedef.
But if I use the first way, In the application I need to declare
lib_t *my_opaque_variable;
If I don't do it that way, I will get a compiler error because it
doesn't know the size of lib_t.
So that would mean the second typedef would be better, because the
compiler will always know the sizeof of a pointer.

So what is the usual way to do this?

Thanks in advance,
Mark

--
<<Remove the del for email>>

Nov 14 '05 #1
19 1374
In <c5**********@news.tudelft.nl> Capstar <sp***@deleg.homeip.net> writes:
I've read some time ago in this NG, that when you're writing a library
it can be good practice to use an opaque type to point to your
structures if the user doesn't need to modify the structure himself.
This way the internal structure of the lib can be changed, and the lib
can be recompiled, but the application using the lib doesn't need to be
recompiled.

But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. I also read somewhere that it's bad
practice to make a typedef to a pointer in such a way that it is not
obvious from looking at the type, in this case lib_t, that it is a
pointer to whatever. So that would mean it would be best to use the
first typedef.
But if I use the first way, In the application I need to declare
lib_t *my_opaque_variable;
If I don't do it that way, I will get a compiler error because it
doesn't know the size of lib_t.
So that would mean the second typedef would be better, because the
compiler will always know the sizeof of a pointer.

So what is the usual way to do this?


The standard C library uses the first approach. FILE stands for the
real thing, and you have to explicitly declare pointers to it.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #2
Capstar <sp***@deleg.homeip.net> wrote:
<snip>
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. I also read somewhere that it's bad
practice to make a typedef to a pointer in such a way that it is not
obvious from looking at the type, in this case lib_t, that it is a
pointer to whatever. So that would mean it would be best to use the
first typedef.
Right.
But if I use the first way, In the application I need to declare
lib_t *my_opaque_variable;
Of course. Any problems with that?
If I don't do it that way, I will get a compiler error because it
doesn't know the size of lib_t.
Yes, for the obvious reason that it cannot tell the size of an
incomplete type until it's actually completed.
So that would mean the second typedef would be better, because the
compiler will always know the sizeof of a pointer.
Wrong conclusion. The compiler _always_ knows the size of a
pointer-to-whatever. What's *not* known to the compiler is the
size of an incomplete type, but that's not is changed at all by
typedef'ing a pointer to that type. Remember: typedef does
*NOT* introduce a new type, only an alias name for an arbitrary
type that already exists.
So what is the usual way to do this?


Stick with the first typedef (if any typedef at all) and use the
pointer notation. Just as you should always use FILE *, and not
any obscure typename alias for it.

HTH
Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #3
Capstar wrote:

I've read some time ago in this NG, that when you're writing a
library it can be good practice to use an opaque type to point
to your structures if the user doesn't need to modify the
structure himself. This way the internal structure of the lib
can be changed, and the lib can be recompiled, but the
application using the lib doesn't need to be recompiled.

But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. I also read somewhere that it's
bad practice to make a typedef to a pointer in such a way that
it is not obvious from looking at the type, in this case lib_t,
that it is a pointer to whatever. So that would mean it would
be best to use the first typedef.
But if I use the first way, In the application I need to declare
lib_t *my_opaque_variable;
If I don't do it that way, I will get a compiler error because
it doesn't know the size of lib_t.
So that would mean the second typedef would be better, because
the compiler will always know the sizeof of a pointer.

So what is the usual way to do this?


The objective is to hide the structure. That means you can never
declare a struct libstruct in the user code, because the size
isn't known. However you can declare a pointer type, because that
size is known. Now you can't malloc any memory for that pointer,
because the size isn't known. That means the library has to have
a routine to do the mallocing and return the pointer. All the
user code can do is save the pointer and return it to various
routines in the library, which know what to do with it. If the
mallocing for the pointer involves mallocing subfields, the
disposal has also to be a library routine.

--
fix (vb.): 1. to paper over, obscure, hide from public view; 2.
to work around, in a way that produces unintended consequences
that are worse than the original problem. Usage: "Windows ME
fixes many of the shortcomings of Windows 98 SE". - Hutchison
Nov 14 '05 #4
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
The objective is to hide the structure. That means you can never
declare a struct libstruct in the user code, because the size
isn't known. However you can declare a pointer type, because that
size is known. Now you can't malloc any memory for that pointer,
because the size isn't known. That means the library has to have
a routine to do the mallocing and return the pointer. All the
user code can do is save the pointer and return it to various
routines in the library, which know what to do with it. If the
mallocing for the pointer involves mallocing subfields, the
disposal has also to be a library routine.


You have accurately described FILE and the way it is handled by the
<stdio.h> part of the standard C library. Yet, for some reason, the
C standard requires the size of FILE to be available to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type, as long as
there is *nothing* useful user code can do with an object of type FILE.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #5
Irrwahn Grausewitz wrote:
Capstar <sp***@deleg.homeip.net> wrote:

<snip>
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. I also read somewhere that it's
bad practice to make a typedef to a pointer in such a way that
it is not obvious from looking at the type, in this case lib_t,
that it is a pointer to whatever. So that would mean it would
be best to use the first typedef.


Right.
But if I use the first way, In the application I need to declare
lib_t *my_opaque_variable;


Of course. Any problems with that?
If I don't do it that way, I will get a compiler error because
it doesn't know the size of lib_t.


Yes, for the obvious reason that it cannot tell the size of an
incomplete type until it's actually completed.
So that would mean the second typedef would be better, because
the compiler will always know the sizeof of a pointer.


Wrong conclusion. The compiler _always_ knows the size of a
pointer-to-whatever. What's *not* known to the compiler is the
size of an incomplete type, but that's not is changed at all by
typedef'ing a pointer to that type. Remember: typedef does
*NOT* introduce a new type, only an alias name for an arbitrary
type that already exists.
So what is the usual way to do this?


Stick with the first typedef (if any typedef at all) and use the
pointer notation. Just as you should always use FILE *, and not
any obscure typename alias for it.


FILE is historically used (and published) so that macros can be
implemented for putc and similar routines. This leads to the
insecurities of those with a little knowledge digging into the
headers and using what they find there. It is only safe with
relative innocents and with experts.

I disagree. The OP needs to know how to declare and publish an
incomplete struct type (else he exposes the internal structure)
and how to complete that definition within the library proper. He
can do all the declaration in the header file(s), and ensure that
the definition is contained only within the c file(s) of the
library proper.

There should be no reason for the library user to know he is
dealing with a pointer. A pointer is probably most convenient
because it has to be passed back to the library routines, and the
memory attached to it probably defines some sort of state. The
memory cannot be declared in the user code without exposing the
structure.

---- libthing.h ----

typedef struct whatzit *lib_t;
lib_t libinit(/*params*/);
int libuse(lib_t lib, /* params */ );
void libclose(lib_t lib);

---- libthing.c ----

#include libthing.h

struct whatzit {
/* as needed */
};

lib_t libinit(...) {....}
int libuse(lib_t lib, ....) {....}
void libclose(lib_t lib);

---- usercode.c ----

#include libthing.h

.....

lib_t thelib;

thelib = libinit(....);
libuse(thelib, ....);
....
libclose(thelib);
.....

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Nov 14 '05 #6
CBFalconer <cb********@yahoo.com> wrote:
Irrwahn Grausewitz wrote:
Capstar <sp***@deleg.homeip.net> wrote: <snippage>
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use. [...] So what is the usual way to do this?
Stick with the first typedef (if any typedef at all) and use the
pointer notation. Just as you should always use FILE *, and not
any obscure typename alias for it.

FILE is historically used (and published) so that macros can be
implemented for putc and similar routines. This leads to the
insecurities of those with a little knowledge digging into the
headers and using what they find there. It is only safe with
relative innocents and with experts.
Nobody claimed otherwise. And still it's good habit to use FILE *
and not something obscure like typedef FILE * fileptr_t;
I disagree. The OP needs to know how to declare and publish an
incomplete struct type (else he exposes the internal structure)
and how to complete that definition within the library proper. He
can do all the declaration in the header file(s), and ensure that
the definition is contained only within the c file(s) of the
library proper.

<snip>

Since you're not contradicting anything I said, may I ask why
you think we disagree?

Regards
--
Irrwahn Grausewitz (ir*******@freenet.de)
welcome to clc: http://www.ungerhu.com/jxh/clc.welcome.txt
clc faq-list : http://www.faqs.org/faqs/C-faq/faq/
clc OT guide : http://benpfaff.org/writings/clc/off-topic.html
Nov 14 '05 #7
On Thu, 15 Apr 2004, Capstar wrote:
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use.


The difference between them is that the second form allows you to
switch from pointers to handles without changing the interface. The
downside is that the programmer needs to be aware that it's either
pointer or an integer type. (*)
Unless you're into paranoid defensive programming I don't think
that's too useful so go with the first.

*)
int libtcmp(lib_t *a, lib_t *b) { return a==b; }
vs
int libtcmp(lib_t a, lib_t b) { return a==b; }

Can you tell whether the latter piece is correct or not without
knowing what type lib_t is?

Nov 14 '05 #8
Capstar wrote:
I've read some time ago in this NG that,
when you're writing a library, it can be good practice
to use an opaque type to point to your structures
if the user doesn't need to modify the structure himself.
This way, the internal structure of the lib can be changed
and the lib can be recompiled
but the application using the lib doesn't need to be recompiled.

But then there are two ways to define the opaque type:

#typedef struct libstruct lib_t;
Yes! Always.
or

#typedef struct libstruct* lib_t;
No! Never.
I'm not sure which one to use. I also read somewhere that
it's bad practice to make a typedef to a pointer
in such a way that it is not obvious from looking at the type
(lib_t in this case) that it is a pointer to whatever.
So that would mean it would be best to use the first typedef.
But if I use the first way,
in the application, I need to declare lib_t* my_opaque_variable;
If I don't do it that way, I will get a compiler error
because it doesn't know the size of lib_t.
So that would mean the second typedef would be better
because the compiler will always know the sizeof of a pointer.

So what is the usual way to do this?


There is no way
to deny a determined hacker direct access to data members.
The only thing you can do is to help prevent application programmers
from *accidently* referencing data members directly.
This can be accomplished by substituting a *public* type definition
with the same *size* and *alignment* as the *private* definition
which does not reveal the private data member names:
#ifdef NCL_REVEAL
/* Reveal type definitions after applications are thoroughly tested. */

typedef struct { /* subvector class definition */
/* private: */
ncl_dhandle H;
ncl_offset O;
ncl_extent N;
ncl_stride S;
} ncl_dsubvector;
/* A subvector does not own the array storage that it references. */
/* It does not allocate any array storage when it is constructed */
/* nor does it deallocate any array storage when it is destroyed. */

#else /* NCL_REVEAL */
/* Conceal type definitions until applications are thoroughly tested. */

#define NCL_DSUBVECTOR_SIZE NCL_SUBVECTOR_SIZE
typedef int ncl_dhidden_subvector[NCL_DSUBVECTOR_SIZE/sizeof(int)];

typedef struct { /* subvector class definition */
/* private: */
ncl_dhidden_subvector V;
} ncl_dsubvector;
/* A subvector does not own the array storage that it references. */
/* It does not allocate any array storage when it is constructed */
/* nor does it deallocate any array storage when it is destroyed. */

#endif /* NCL_REVEAL */
The problem with passing pointers to opaque objects is that
all library functions which must access the private data members
must be compiled externally and linked into the application program.
Light-weight operations cannot be implemented
as inline functions or C preprocessor macros without including
the private type definition in the application program.

Take a look at "The ANSI C Numerical Class Library"

http://www.netwood.net/~edwin/svmtl/

if this is of any interest to you.

Nov 14 '05 #9
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
The objective is to hide the structure. That means you can never
declare a struct libstruct in the user code, because the size
isn't known. However you can declare a pointer type, because that
size is known. Now you can't malloc any memory for that pointer,
because the size isn't known. That means the library has to have
a routine to do the mallocing and return the pointer. All the
user code can do is save the pointer and return it to various
routines in the library, which know what to do with it. If the
mallocing for the pointer involves mallocing subfields, the
disposal has also to be a library routine.


You have accurately described FILE and the way it is handled by the
<stdio.h> part of the standard C library. Yet, for some reason, the
C standard requires the size of FILE to be available to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type, as long as
there is *nothing* useful user code can do with an object of type FILE.


In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 14 '05 #10
Capstar <sp***@deleg.homeip.net> writes:
[...]
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

[...]

Quibble: typedef is not a preprocessor directive; there's no '#'.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
Schroedinger does Shakespeare: "To be *and* not to be"
Nov 14 '05 #11
Jarno A Wuolijoki wrote:
On Thu, 15 Apr 2004, Capstar wrote:
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;

I'm not sure which one to use.


The difference between them is that the second form allows you to
switch from pointers to handles without changing the interface. The
downside is that the programmer needs to be aware that it's either
pointer or an integer type. (*)
Unless you're into paranoid defensive programming I don't think
that's too useful so go with the first.

*)
int libtcmp(lib_t *a, lib_t *b) { return a==b; }
vs
int libtcmp(lib_t a, lib_t b) { return a==b; }

Can you tell whether the latter piece is correct or not without
knowing what type lib_t is?


You shouldn't be programming this operation unless you are
programming the library. That is the point of keeping the type to
yourself. So you don't need to know.

--
fix (vb.): 1. to paper over, obscure, hide from public view; 2.
to work around, in a way that produces unintended consequences
that are worse than the original problem. Usage: "Windows ME
fixes many of the shortcomings of Windows 98 SE". - Hutchison
Nov 14 '05 #12
Keith Thompson wrote:
Capstar <sp***@deleg.homeip.net> writes:
[...]
But then there are two ways to define the opque type:
#typedef struct libstruct lib_t;
or
#typedef struct libstruct * lib_t;


[...]

Quibble: typedef is not a preprocessor directive; there's no '#'.


d'oh! what was I thinking...

--
<<Remove the del for email>>

Nov 14 '05 #13
Thanks for all your quick replies.
I think I will stick to
typedef struct libstruct lib_t;

and declare
lib_t *my_opaque_variable;

I know I won't be able to use inline functions or macros for lightweight
functions, but I do have the ability to modify the structure without the
need to recompile to application.

Mark

--
<<Remove the del for email>>

Nov 14 '05 #14
"CBFalconer" <cb********@yahoo.com> wrote in message
news:40***************@yahoo.com...
Dan Pop wrote:
... for some reason, the C standard requires the size of FILE to be
available to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type,
as long as there is *nothing* useful user code can do with an
object of type FILE.


In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.


What would preclude an implementation of putc as a (non-trivial) macro if
FILE were an incomplete type?

Consider...

struct __FILE {
int foo;
...
};

typedef struct __file FILE;

#define __F(f) ((struct __FILE *) (f))

#define putc(c,f) (__F(f)->foo ? ...)

This would probably be too tedious for implementors to bother with, and it
seems to me that about the only thing the language would gain from an
incomplete FILE type is that some implementations could naturally diagnose
code like...

FILE x = *stdin;

--
Peter
Nov 14 '05 #15
On Fri, 16 Apr 2004, CBFalconer wrote:
int libtcmp(lib_t *a, lib_t *b) { return a==b; }
vs
int libtcmp(lib_t a, lib_t b) { return a==b; }

Can you tell whether the latter piece is correct or not without
knowing what type lib_t is?


You shouldn't be programming this operation unless you are
programming the library. That is the point of keeping the type to
yourself. So you don't need to know.


Oh well.. I think requiring bloating the interface with extra
macro/function just to know whether two variables refer to the very
same entity underlines the point even better;)

Nov 14 '05 #16
Peter Nilsson wrote:
"CBFalconer" <cb********@yahoo.com> wrote in message
Dan Pop wrote:

... for some reason, the C standard requires the size of FILE
to be available to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type,
as long as there is *nothing* useful user code can do with an
object of type FILE.


In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.


What would preclude an implementation of putc as a (non-trivial)
macro if FILE were an incomplete type?

Consider...

struct __FILE {
int foo;
...
};


That is neither an opaque type nor an incomplete type.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 14 '05 #17
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
The objective is to hide the structure. That means you can never
declare a struct libstruct in the user code, because the size
isn't known. However you can declare a pointer type, because that
size is known. Now you can't malloc any memory for that pointer,
because the size isn't known. That means the library has to have
a routine to do the mallocing and return the pointer. All the
user code can do is save the pointer and return it to various
routines in the library, which know what to do with it. If the
mallocing for the pointer involves mallocing subfields, the
disposal has also to be a library routine.


You have accurately described FILE and the way it is handled by the
<stdio.h> part of the standard C library. Yet, for some reason, the
C standard requires the size of FILE to be available to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type, as long as
there is *nothing* useful user code can do with an object of type FILE.


In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.


Engage your brain, Chuck. These things are written by the implementor
and there is no way to hide the actual defintion of FILE from him ;-)

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #18
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:

The objective is to hide the structure. That means you can never
declare a struct libstruct in the user code, because the size
isn't known. However you can declare a pointer type, because that
size is known. Now you can't malloc any memory for that pointer,
because the size isn't known. That means the library has to have
a routine to do the mallocing and return the pointer. All the
user code can do is save the pointer and return it to various
routines in the library, which know what to do with it. If the
mallocing for the pointer involves mallocing subfields, the
disposal has also to be a library routine.

You have accurately described FILE and the way it is handled by
the <stdio.h> part of the standard C library. Yet, for some
reason, the C standard requires the size of FILE to be available
to user code:

2 The types declared are size_t (described in 7.17);

FILE

which is an object type...
^^^^^^^^^^^^^^

I've never understood why FILE can't be an incomplete type, as
long as there is *nothing* useful user code can do with an
object of type FILE.


In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.


Engage your brain, Chuck. These things are written by the
implementor and there is no way to hide the actual defintion of
FILE from him ;-)


Time to engage yours. :-) The macro is expanded by the user in
his own little world. How does that expansion get at the various
fields of the FILE structure if that structure is hidden? Are you
recommending the implementor evaluate offsetof(...) for every
field in FILE and insert corresponding absolute values into his
macros? Along with the appropriate casts. Sounds like a
maintenance nightmare to me.

To avoid all this the implementor publishes the actual FILE
structure in stdio.h and makes no fuss about it. He uses those
fields (which are in his namespace) in putc and getc macros, and
again makes no fuss about it. Joe Q. User uses them and never
sees them. Until he gets some knowledge and goes looking. Then
he finds he can use those funny names with preceding '_'s to get
at interesting things and make trouble.

Now look at something that has a truly opaque type, such as my
hashlib package. hashlib.h has the statement:

/* opaque incomplete object */
typedef struct hshtag hshtbl;

and "hshtbl *" is the type returned by hshinit(). Every function
call into the library has an initial parameter of type "hshtbl
*". The user never sees the completed definition, and has no C
language means of accessing any field of a hshtbl. If I were
doing it again I would move the * into the typedef and obscure the
fact that it is a pointer. As long as I don't alter the .h file I
can do anything I want in the implementation (.c) portion.

However I can never publish any macros that deal with a hshtbl.
Luckily all operations on the table are sufficiently complex that
the overhead of a function call will never be noticed.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 14 '05 #19

In article <c5***********@sunnews.cern.ch>, Da*****@cern.ch (Dan Pop) writes:
In <40***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
In order to allow putc and getc to be implemented as macros, and
put/get things from a buffer embedded in the FILE structure, and
such like.


Engage your brain, Chuck. These things are written by the implementor
and there is no way to hide the actual defintion of FILE from him ;-)


But if FILE is an incomplete type in a given translation unit, then
putc in that t.u. can't be a function-like macro that expands into
code which refers to members of the FILE type. So if the implementor
wants to provide a macro version of putc, it must be accompanied by a
complete FILE type.

Still, it's odd that the Standard would *require* that FILE be an
object type, rather than simply allowing it. If it were legal for a
user program to copy FILE objects (say, for the purpose of saving and
restoring state), then it might make sense; but C90 7.9.3 states that
"a copy of a FILE object may not necessarily serve in place of the
original".

So while I agree with Chuck that there are reasons to allow FILE to
be an object type, I also agree with Dan that an implementation
ought to be allowed to make it an incomplete type, since there
doesn't appear to be any valid mandated use for FILE as an object
type in the standard.

But I may be missing something...

--
Michael Wojcik mi************@microfocus.com

This book uses the modern technology to explain the phenomemon in the world
of Japanese animation. If you love anime so much, you'd better read this.
After you read it, you may agree that is destroying the dream of the child.
Needs Chinese viewing system. -- The Goodboy Scientific
Nov 14 '05 #20

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.