Incomplete types

J

John Taylor

Hello,

I learned there are object types (describe objects) and function types
(describe functions). Truly there are also incomplete types, but I can't
understood what they really are. I read void is an incomplete type. The
(C99) standard says incomplete types describes objects, too, but "lack
information needed to determine their sizes". How can you have an object
without knowing its size? If you have an object, you know its size, just
by counting the bits required by any of its values. You can answer: "The
void type comprises an empty set of values": if you have no values, you
cannot count the number of bits required by any value. The point is that
in my understanding void should not describe objects at all. An object
can have a size of zero if the only value it can assume is the empty
string of bits. But there still is a value in this case. Mathematically,
the void type seems to be different from the {{}} set. It seems to be
the empty set ({}). Also, can you name some other incomplete type
different from void, please?

Thanks.
 
J

John Taylor

Sorry but your examples looks too complex for me (not your fault
obviously, my fault). I haven't studied structures and pointers yet.
 
J

John Taylor

pete said:
/*
** struct inc_1 is an incomplete type.
** arr is of an incomplete type.
*/

/* BEGIN new.c */

int main(void)
{
struct inc_1;
extern int arr[];
struct inc_1 *p1 = 0;

return 0;
}

/* END new.c */

I didn't know you can create arrays of unspecified size. How can the
compiler know how much space to allocate for such an object?
 
Joined
Sep 30, 2009
Messages
1
Reaction score
0
John Taylor said:
pete wrote:
> /*
> ** struct inc_1 is an incomplete type.
> ** arr is of an incomplete type.
> */
>
> /* BEGIN new.c */
>
> int main(void)
> {
> struct inc_1;
> extern int arr[];
> struct inc_1 *p1 = 0;
>
> return 0;
> }
>
> /* END new.c */


I didn't know you can create arrays of unspecified size. How can the
compiler know how much space to allocate for such an object?
/*you'll have to declare array as dynamic memory allocation by using--
int p;
p=(int *)malloc(len+1) /*+1 for accomodating \0*/
--like this*/
 
W

Willem

John Taylor wrote:
) pete wrote:
<snip>
)> extern int arr[];
)
) I didn't know you can create arrays of unspecified size. How can the
) compiler know how much space to allocate for such an object?

The array is not being created there. It's only being declared.
Basically it's saying "During linking, some other module will define
an array of int called 'arr' of a size we don't know right now"

Although I'm not quite sure this is legal; what happens to sizeof(arr) ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
J

jacob navia

Richard Heathfield a écrit :
That would be a great example, if only FILE were an incomplete type!
:) It is, however, still a /good/ example, since FILE might as well
be an incomplete type from a normal portable-C-programmer's
perspective. (I specifically exclude /ab/normal
portable-C-programmers from that!)

In the lcc-win 64 bit version FILE *is* an opaque type.
My stdio.h just does

struct __FILE;
typedef struct __FILE FILE;
extern FILE *_Files[];
#define stdin (_Files[0])
#define stdout (_Files[1])
#define stderr (_Files[2])

I hope I haven't done something wrong because all the new stdio run time
seems to work and nowhere is a user visible definition of FILE.
 
B

Ben Bacarisse

Willem said:
John Taylor wrote:
) pete wrote:
<snip>
)> extern int arr[];
)
) I didn't know you can create arrays of unspecified size. How can the
) compiler know how much space to allocate for such an object?

The array is not being created there. It's only being declared.
Basically it's saying "During linking, some other module will define
an array of int called 'arr' of a size we don't know right now"

Although I'm not quite sure this is legal; what happens to
sizeof(arr) ?

It's "legal". sizeof arr is not -- it is a constraint violation and
so must be diagnosed by the implementation.
 
J

jacob navia

Richard Heathfield a écrit :
That's a conformance issue; it violates 7.19.1(2), which requires that
FILE be an object type - i.e. a type that fully describes an object.

7.19.1(2) says:
FILE
which is an object type capable of recording all the information needed to control a
stream, including its file position indicator, a pointer to its associated buffer (if any), an
error indicator that records whether a read/write error has occurred, and an end-of-file
indicator that records whether the end of the file has been reached

Nowhere do I read that this object type *internals* must be disclosed...

I have all the required fields in the FILE object, only, you can't access them.
 
J

jacob navia

Richard Heathfield a écrit :
Look up "object type" - it's defined as "type that fully describes the
object".


In which case the type does not fully describe the object, and
therefore FILE is not an object type.

Well, that was it. I will leave it at that. Non conformant but I can't disclose
the FILE type since there are many things that can (and will) change. I will
rewrite that later, when some (paying) customer complains

:)
 
B

bartc

Look up "object type" - it's defined as "type that fully describes the
object".


In which case the type does not fully describe the object, and
therefore FILE is not an object type.

What are the practical consequences of FILE not being an object type?
 
K

Kalle Olavi Niemitalo

Richard Heathfield said:
That's a conformance issue; it violates 7.19.1(2), which requires that
FILE be an object type - i.e. a type that fully describes an object.

Why does the standard require that? I see no benefit to the
programmer, and a possible disadvantage to the implementor:
if one wanted to add more members to the FILE structure,
it would be handy to know that no user program can depend
on the old size.
 
P

Phil Carmody

Ben Bacarisse said:
Willem said:
John Taylor wrote:
) pete wrote:
<snip>
)> extern int arr[];
)
) I didn't know you can create arrays of unspecified size. How can the
) compiler know how much space to allocate for such an object?

The array is not being created there. It's only being declared.
Basically it's saying "During linking, some other module will define
an array of int called 'arr' of a size we don't know right now"

Although I'm not quite sure this is legal; what happens to
sizeof(arr) ?

It's "legal".

arr is a unary expression that has an incomplete type, so it's a
contraint violation, surely?

Phil
 
K

Keith Thompson

jacob navia said:
Richard Heathfield a écrit :

7.19.1(2) says:
FILE
which is an object type capable of recording all the information
needed to control a stream, including its file position indicator, a
pointer to its associated buffer (if any), an error indicator that
records whether a read/write error has occurred, and an end-of-file
indicator that records whether the end of the file has been reached

Nowhere do I read that this object type *internals* must be disclosed...

I have all the required fields in the FILE object, only, you can't
access them.

I believe this program is strictly conforming; if FILE is not an
object type, it will probably fail to compile:

#include <stdio.h>
int main(void)
{
sizeof(FILE); /* result is discarded */
return 0;
}

This applies to both C90 and C99.

The type definition needn't expose any internal details other than the
size. For example, you could have:

typedef unsigned char[32] FILE;

assuming that 32 bytes is enough to hold the required information.
You could then declare an internal type, say _FILE, and use pointer
conversion in your library to access the actual information.

I know of no *practical* drawbacks to making FILE an incomplete type,
and frankly I think that particular requirement is a bit silly.
Nevertheless, it is a requirement of the standard, and I believe
you could meet it without any major changes to your implementation.
(Getting the size right might be moderately tricky.)

Whether you consider it worth your time to meet this requirement is,
as always, entirely up to you.

Let me be very clear. I am telling you that an implementation with
FILE as an incomplete type does not fully conform to the C90 or
C99 standard. My only purpose is to convey this information to you.
I am not advising you or asking you either to do anything about it
or not to do anything about it.
 
B

Ben Bacarisse

Phil Carmody said:
Ben Bacarisse said:
Willem said:
John Taylor wrote:
) pete wrote:
<snip>
)> extern int arr[];
)
) I didn't know you can create arrays of unspecified size. How can the
) compiler know how much space to allocate for such an object?

The array is not being created there. It's only being declared.
Basically it's saying "During linking, some other module will define
an array of int called 'arr' of a size we don't know right now"

Although I'm not quite sure this is legal; what happens to
sizeof(arr) ?

It's "legal".

arr is a unary expression that has an incomplete type, so it's a
contraint violation, surely?

Yes. Why did you snip the part where i said that it was a constraint
violation (the very next few words, IIRC)?

I took Willem's "Although I'm not quite sure this is legal" to refer
to the extern and I was just confirming that is was.
 
S

Seebs

That's a conformance issue; it violates 7.19.1(2), which requires that
FILE be an object type - i.e. a type that fully describes an object.

Interesting! I was in the past under the impression that it was generally
accepted that implementors were allowed to do just this. I wonder
whether that's an intentional change in response to some issue, or just
a side-effect of some other change.

-s
 
S

Seebs

Nowhere do I read that this object type *internals* must be disclosed...

See 6.2.5:

Types are partitioned into object types (types that fully describe
objects), function types (types that describe functions), and
incomplete types (types that describe objects but lack information
needed to determine their sizes).

If you can't do sizeof(*stdin), so far as I can tell, you're not providing
an object type.

-s
 
F

Flash Gordon

jacob said:
Richard Heathfield a écrit :

Well, that was it. I will leave it at that. Non conformant but I can't
disclose
the FILE type since there are many things that can (and will) change. I
will
rewrite that later, when some (paying) customer complains

:)

Entirely your choice.

Of course, you could do something like...
typedef unsigned char FILE[__FILESIZE];
Then, in your implementation of the C library, simply cast it to the
correct type. This would hide all the details whilst still meeting the
requirements.

Of course, one disadvantage to hiding the details is that your getc/putc
macros cannot as easily take advantage of the freedoms they have, since
it is rather harder for them to directly access the buffer!
 
P

Phil Carmody

Ben Bacarisse said:
Phil Carmody said:
Ben Bacarisse said:
John Taylor wrote:
) pete wrote:
<snip>
)> extern int arr[];
)
) I didn't know you can create arrays of unspecified size. How can the
) compiler know how much space to allocate for such an object?

The array is not being created there. It's only being declared.
Basically it's saying "During linking, some other module will define
an array of int called 'arr' of a size we don't know right now"

Although I'm not quite sure this is legal; what happens to
sizeof(arr) ?

It's "legal".

arr is a unary expression that has an incomplete type, so it's a
contraint violation, surely?

Yes. Why did you snip the part where i said that it was a constraint
violation (the very next few words, IIRC)?

Because meaning should be delivered in a forward direction. Forward
context should be unnecessary.

That, and he mentioned "sizeof(arr)", and you later mentioned "sizeof arr".
Syntactically these are different things.

Phil
 
J

James Kuyper

Richard said:
You may or may not consider non-conformance to be a practical problem.

I think you're addressing the wrong question. I suspect he was asking
about what the practical consequences would be if the standard removed
that requirement, so that it would no longer be a conformance issue.
The following program is strictly conforming:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
return sizeof(FILE) > 0 ? EXIT_SUCCESS : EXIT_FAILURE;
}

This program /must/ return EXIT_SUCCESS. But if FILE is an incomplete
type, then the program won't even compile. I think that's a big deal.
YMMV.

Considered in terms of a possible relaxation of the standard's
requirements, I don't think it's a big deal. Because of 7.19.3p6 "The
address of the FILE object used to control a stream may be significant;
a copy of a FILE object need not serve in place of the original.".
Primarily as a result of that clause, there's very little, if anything,
that you can usefully do with FILE objects that would require knowledge
of their size.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top