By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,041 Members | 1,051 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,041 IT Pros & Developers. It's quick & easy.

struct type completion

P: n/a
I'm trying to understand how structure type completion works.

# A structure or union type of unknown
# content (as described in 6.7.2.3) is an incomplete type. It
# is completed, for all declarations of that type, by
^^^
# declaring the same structure or union tag with its defining
# content later in the same scope.
^^^^^
(6.2.5#23)

# [#3] All declarations of structure, union, or enumerated
^^^
# types that have the same scope and use the same tag declare
^^^^^^^^^^^^
# the same type. The type is incomplete100) until the
^^^^^^^^^^^^^^
# closing brace of the list defining the content, and complete
# thereafter.
(6.7.2.3#3)
(both excerpts are from n869.txt, but they're the same in the Std)

So (eg. in a file scope):

/* 1 */ struct mystruct object;
/* 2 */ struct mystruct { /*...*/ };

line 1 defines `object' (although at this point the body of `struct
mystruct' is not yet known(?)); and line 1 does not work without
line 2.

What I don't understand is, that the excerpts above seem to dictate
that line 2 fully defines the type for all instances of `struct mystruct'.
The type in line 1 must be a complete type; if it were not, then it would
not be the same type as in line 2, which seems to be required by the
second quote; and - what's obvious - we could not define `object' (we
can't define an object with incomplete type, can we?).

But then further description seems to contradict this: "... incomplete
until the closing brace ...". If the type in line 1 is complete, then
it needn't be completed, and can't of course be incomplete at the
same time.

If I add this definition:
/* test */ int test[sizeof object];
after line 1, then I get a compiler error; whereas I move it after
line 2, everything is okay. In the first case it is stunning
that I can define an object, but I can't take its size.

Could you please explain this to me? - many thanks!

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
On Mon, 18 Apr 2005 15:12:46 +0000, S.Tobias wrote:
I'm trying to understand how structure type completion works.

# A structure or union type of unknown
# content (as described in 6.7.2.3) is an incomplete type. It
# is completed, for all declarations of that type, by
^^^
# declaring the same structure or union tag with its defining
# content later in the same scope.
^^^^^
(6.2.5#23)

# [#3] All declarations of structure, union, or enumerated
^^^
# types that have the same scope and use the same tag declare
^^^^^^^^^^^^
# the same type. The type is incomplete100) until the
^^^^^^^^^^^^^^
# closing brace of the list defining the content, and complete
# thereafter.
(6.7.2.3#3)
(both excerpts are from n869.txt, but they're the same in the Std)

So (eg. in a file scope):

/* 1 */ struct mystruct object;
/* 2 */ struct mystruct { /*...*/ };

line 1 defines `object' (although at this point the body of `struct
mystruct' is not yet known(?)); and line 1 does not work without
line 2.
Line 1 is invalid. When you define an object the type must be complete at
the point of definition, it cannot be completed later. Note that you can
define a pointer to an incomplete type whch is completed later. All
pointer types are object types, even pointers to incomplete or function
types.
What I don't understand is, that the excerpts above seem to dictate that
line 2 fully defines the type for all instances of `struct mystruct'.
The type in line 1 must be a complete type; if it were not, then it
would not be the same type as in line 2, which seems to be required by
the second quote; and - what's obvious - we could not define `object'
(we can't define an object with incomplete type, can we?).
At the point that line 1 is translated its type is incomplete. For any
code after line 2 it would appear complete (except of course that it is
invalid). So taking a valid example

/* 1 */ struct mystruct *ptr;

/* sizeof *ptr is invalid here */

/* 2 */ struct mystruct { /*...*/ };

/* sizeof *ptr is valid here because it is equivalent to
sizeof(struct mystruct) which is now complete */
But then further description seems to contradict this: "... incomplete
until the closing brace ...". If the type in line 1 is complete, then
it needn't be completed, and can't of course be incomplete at the same
time.


A type can be incomplete at one point in the source file and then complete
later on.

Lawrence
Nov 14 '05 #2

P: n/a
Lawrence Kirby <lk****@netactive.co.uk> wrote:
On Mon, 18 Apr 2005 15:12:46 +0000, S.Tobias wrote:
Thank you very much for answering. However I disagree with you.
I'm trying to understand how structure type completion works.

# A structure or union type of unknown
# content (as described in 6.7.2.3) is an incomplete type. It
# is completed, for all declarations of that type, by
^^^
# declaring the same structure or union tag with its defining
# content later in the same scope.
^^^^^
(6.2.5#23)

# [#3] All declarations of structure, union, or enumerated
^^^
# types that have the same scope and use the same tag declare
^^^^^^^^^^^^
# the same type. The type is incomplete100) until the
^^^^^^^^^^^^^^
# closing brace of the list defining the content, and complete
# thereafter.
(6.7.2.3#3)
(both excerpts are from n869.txt, but they're the same in the Std)

So (eg. in a file scope):

/* 1 */ struct mystruct object;
/* 2 */ struct mystruct { /*...*/ };

line 1 defines `object' (although at this point the body of `struct
mystruct' is not yet known(?)); and line 1 does not work without
line 2. Line 1 is invalid.
I have tried this code with como and gcc, and both exhibit exactly
same behaviour - try it for yourself: compile as is (ok), delete
line 2 (error), insert line "test" after line 1 (error), move it
after line 2 (ok).
When you define an object the type must be complete at
the point of definition, it cannot be completed later.
Yes, I think so too.
Note that you can
define a pointer to an incomplete type whch is completed later. All
pointer types are object types, even pointers to incomplete or function
types.
I'm quite aware of that. You don't even have to complete the type
(unless you dereference the ptr) - the pointer is still valid. But this
is not what I want to talk about, and I really do mean an object where
I put the identifier `object'.

The code is a corner case I wanted to check after reading the above
quotes from the Standard. I think that they say that struct types
can be completed later. Please pay attention to the words I underlined;
I hope you can either agree to my interpretation, or understand
the reason to my misunderstanding and correct me.

Reminder: identifiers have the same scope, when their scopes end
at the same point. Above, the scopes of the declarations are different
(they start at different places), but both declarations have the same
scope (cf. 6.2.1 p. 6 and 7).
What I don't understand is, that the excerpts above seem to dictate that
line 2 fully defines the type for all instances of `struct mystruct'.
The type in line 1 must be a complete type; if it were not, then it
would not be the same type as in line 2, which seems to be required by
the second quote; and - what's obvious - we could not define `object'
(we can't define an object with incomplete type, can we?). At the point that line 1 is translated its type is incomplete. For any
code after line 2 it would appear complete (except of course that it is
invalid).
I thought so too. But this seems to contradict eg. the second quote
(both in fact): both declarations use the same tag, therefore they
declare the *same* type; a type cannot be both complete and incomplete.

[snipped example for pointers - agree, but a different matter]

I assume the type is complete (first quote), that is, both declarations
declare complete type (whatever incredible that sounds). However
the last sentence of the second quote seems to contradict it:
But then further description seems to contradict this: "... incomplete
until the closing brace ...". If the type in line 1 is complete, then
it needn't be completed, and can't of course be incomplete at the same
time.


(As I read it now, I think it may be understood that closing brace
completes the type, even for earlier declarations; hence there would
be no disagreement. But still, the wording is very contrived -
it would be simpler to say the definition of the (complete) struct
type may be found later in the translation unit.)
A type can be incomplete at one point in the source file and then complete
later on.


Hmmm.... I don't have an answer to that, but I strongly disagree.
If one is incomplete, the other complete, then they're different types,
I thought that was pretty logical. Could you give some example, or
a reference (c&v), please?

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #3

P: n/a
S.Tobias wrote:
Lawrence Kirby <lk****@netactive.co.uk> wrote:
S.Tobias wrote:
So (eg. in a file scope):

/* 1 */ struct mystruct object;
/* 2 */ struct mystruct { /*...*/ };

line 1 defines `object' (although at this point the body of `struct
mystruct' is not yet known(?)); and line 1 does not work without
line 2.


Line 1 is invalid.


I have tried this code with como and gcc, and both exhibit exactly
same behaviour - try it for yourself: compile as is (ok), delete
line 2 (error), insert line "test" after line 1 (error), move it
after line 2 (ok).


Line 1 is a "tentative definition" (see 6.9.2 in N869).
It is a kind of forward declaration for objects.

To paraphrase the standard, Line 1 declares that 'object' is
the name of an object that will be declared elsewhere in the file.
The object will be of type 'struct mystruct' which is currently
an incomplete type.

If the end of file is reached and 'object' does not have a
full definition (ie. a definition with initializer), then the
compiler will add a line:

struct mystruct object = { 0 };

to the end of the file, and compile that.

Tentative definitions are permitted to have incomplete type,
as long as the type has been completed by the time end-of-file
is reached. If you delete Line 2 you will get a compiler error.

If you put Line 1 and Line 2 inside a function (where tentative
definitions are invalid), you will get a compiler error on Line 1.

Nov 14 '05 #4

P: n/a
On Mon, 18 Apr 2005 19:03:54 +0000, S.Tobias wrote:
Lawrence Kirby <lk****@netactive.co.uk> wrote:
On Mon, 18 Apr 2005 15:12:46 +0000, S.Tobias wrote:
Thank you very much for answering. However I disagree with you.
> I'm trying to understand how structure type completion works.
>
> # A structure or union type of unknown
> # content (as described in 6.7.2.3) is an incomplete type. It
> # is completed, for all declarations of that type, by
> ^^^
> # declaring the same structure or union tag with its defining
> # content later in the same scope.
> ^^^^^
> (6.2.5#23)
>
> # [#3] All declarations of structure, union, or enumerated
> ^^^
> # types that have the same scope and use the same tag declare
> ^^^^^^^^^^^^
> # the same type. The type is incomplete100) until the
> ^^^^^^^^^^^^^^
> # closing brace of the list defining the content, and complete
> # thereafter.
> (6.7.2.3#3)
> (both excerpts are from n869.txt, but they're the same in the Std)
>
> So (eg. in a file scope):
>
> /* 1 */ struct mystruct object;
> /* 2 */ struct mystruct { /*...*/ };
>
> line 1 defines `object' (although at this point the body of `struct
> mystruct' is not yet known(?)); and line 1 does not work without
> line 2.
Line 1 is invalid.


I have tried this code with como and gcc, and both exhibit exactly
same behaviour - try it for yourself: compile as is (ok), delete
line 2 (error), insert line "test" after line 1 (error), move it
after line 2 (ok).


Yes, my error. Tentative definitions are allowed to have incomplete type
as long as they don't have internal linkage, I overlooked the last part.
When you define an object the type must be complete at
the point of definition, it cannot be completed later.


Yes, I think so too.
Note that you can
define a pointer to an incomplete type whch is completed later. All
pointer types are object types, even pointers to incomplete or function
types.


I'm quite aware of that. You don't even have to complete the type
(unless you dereference the ptr) - the pointer is still valid. But this
is not what I want to talk about, and I really do mean an object where
I put the identifier `object'.

The code is a corner case I wanted to check after reading the above
quotes from the Standard. I think that they say that struct types
can be completed later. Please pay attention to the words I underlined;
I hope you can either agree to my interpretation, or understand
the reason to my misunderstanding and correct me.


I guess it comes down to what it means by "the same type".
Reminder: identifiers have the same scope, when their scopes end
at the same point. Above, the scopes of the declarations are different
(they start at different places), but both declarations have the same
scope (cf. 6.2.1 p. 6 and 7).
Yes, they have the same scope, and of course the same tag.
> What I don't understand is, that the excerpts above seem to dictate that
> line 2 fully defines the type for all instances of `struct mystruct'.
> The type in line 1 must be a complete type; if it were not, then it
> would not be the same type as in line 2, which seems to be required by
> the second quote; and - what's obvious - we could not define `object'
> (we can't define an object with incomplete type, can we?).
At the point that line 1 is translated its type is incomplete. For any
code after line 2 it would appear complete (except of course that it is
invalid).


I thought so too. But this seems to contradict eg. the second quote
(both in fact): both declarations use the same tag, therefore they
declare the *same* type; a type cannot be both complete and incomplete.


Not at a particular point in the code, but it can at different points in
the code. It is much the same issue as with function prototypes. If you
have

void foo();

foo(x);

void foo(void);

foo(x);

then the rules that apply to the first foo(x); are different to the
second: the second sees the composite type that includes the prototype.
[snipped example for pointers - agree, but a different matter]

I assume the type is complete (first quote), that is, both declarations
declare complete type (whatever incredible that sounds). However
the last sentence of the second quote seems to contradict it:
> But then further description seems to contradict this: "... incomplete
> until the closing brace ...". If the type in line 1 is complete, then
> it needn't be completed, and can't of course be incomplete at the same
> time.
(As I read it now, I think it may be understood that closing brace
completes the type, even for earlier declarations; hence there would
be no disagreement. But still, the wording is very contrived -
it would be simpler to say the definition of the (complete) struct
type may be found later in the translation unit.)
It is a clear indication that the completeness of a type can change
depending on from what point in the source code you view it.
A type can be incomplete at one point in the source file and then complete
later on.


Hmmm.... I don't have an answer to that, but I strongly disagree.


If one is incomplete, the other complete, then they're different types,
I thought that was pretty logical. Could you give some example, or
a reference (c&v), please?


The wording of the standard you quote above depends on this. A type can
be incomplete at one point in the source code and complete later on. "The
same type" here is simply the opposite of "distinct types".

Consider

{
struct foo { int x } a;
}

{
struct foo { int x } b;
}

a and b have 2 distinct types here, and they are incompatible. Given your
example
> /* 1 */ struct mystruct object;
> /* 2 */ struct mystruct { /*...*/ };


the fact that the 2 lines refer to the same type means that the completing
of the type in the second line affects the type of object because they are
the same type. So after line 2 (sizeof object) is valid, which it wouldn't
be if they weren't the same type. I think that is all it is saying.

The wording of the standard may not be perfect in this case but I don't
see room for ambiguity. Maybe you could consider that completing the type
doesn't change the type as such, but just changes what you are allowed to
do with it from that point in the code.

Lawrence
Nov 14 '05 #5

P: n/a
Old Wolf <ol*****@inspire.net.nz> wrote:
S.Tobias wrote:
S.Tobias wrote:
So (eg. in a file scope):

/* 1 */ struct mystruct object;
/* 2 */ struct mystruct { /*...*/ };
[snip] I have tried this code with como and gcc, and both exhibit exactly
same behaviour - try it for yourself: compile as is (ok), delete
line 2 (error), insert line "test" after line 1 (error), move it
after line 2 (ok).
Line 1 is a "tentative definition" (see 6.9.2 in N869).
It is a kind of forward declaration for objects. [snip]

It was an "unfriendly interference of unrelated features".
I should have tested that code in block scope - my fault, I was
too blindly believing what I had understood.
Thank you for your input, that has cleared the way for me!
If you put Line 1 and Line 2 inside a function (where tentative
definitions are invalid), you will get a compiler error on Line 1.


Indeed, 6.7#7 has it explicitly.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #6

P: n/a
Lawrence Kirby <lk****@netactive.co.uk> wrote:
On Mon, 18 Apr 2005 19:03:54 +0000, S.Tobias wrote:
Lawrence Kirby <lk****@netactive.co.uk> wrote:
On Mon, 18 Apr 2005 15:12:46 +0000, S.Tobias wrote:
(I gave more context for the first quote.)

# [#23] An array type of unknown size is an incomplete type.
# It is completed, for an identifier of that type, by
# specifying the size in a later declaration (with internal or
# external linkage). A structure or union type of unknown
# content (as described in 6.7.2.3) is an incomplete type. It
# is completed, for all declarations of that type, by
# declaring the same structure or union tag with its defining
# content later in the same scope.

What I think what this says regarding the structs is this:

With array types:
/* file scope */
int a[], b[];
(`a' and `b' have same type here)
int a[5];
int b[7];
Now we have re-declared and the identifiers `a' and `b' have different
types. We need to re-declare the identifiers to complete their type.

With struct types this is a bit different:
struct s *p;
struct s o; /* in file scope only */
(`*p' and `o' expressions have same, incomplete type)
struct s { ... };
The above definition of `struct s' also causes all previous identifiers
to be *implicitly* re-declared with the new complete type. So from now on
`o' and `*p' are complete types.

I think the following change would improve that fragment:
[...] It is completed, for all declarations [of identifiers]
of that type, by [...]

# [#3] All declarations of structure, union, or enumerated
# types that have the same scope and use the same tag declare
# the same type. The type is incomplete100) until the
# closing brace of the list defining the content, and complete
# thereafter.

I have thought about this one a lot, but I can't reach any conclusion.
> So (eg. in a file scope):
> /* 1 */ struct mystruct object;
> /* 2 */ struct mystruct { /*...*/ };
> line 1 defines `object' (although at this point the body of `struct
> mystruct' is not yet known(?)); and line 1 does not work without
> line 2.

Line 1 is invalid. [snip] Yes, my error. Tentative definitions are allowed to have incomplete type
as long as they don't have internal linkage, I overlooked the last part.
Mine too - I thought it would always work, but I hadn't checked it
(thanks, Old Wolf). In fact your previous example with a pointer
to struct was better (more general) - I'm sorry for snipping it
away too hastily.

[...] I guess it comes down to what it means by "the same type".
8-O You aren't a lawer, are you? ;-)

[snip]
At the point that line 1 is translated its type is incomplete. For any
code after line 2 it would appear complete (except of course that it is
invalid).


I thought so too. But this seems to contradict eg. the second quote
(both in fact): both declarations use the same tag, therefore they
declare the *same* type; a type cannot be both complete and incomplete. Not at a particular point in the code, but it can at different points in
the code. It is much the same issue as with function prototypes. If you
have void foo(); foo(x); void foo(void); foo(x); then the rules that apply to the first foo(x); are different to the
second: the second sees the composite type that includes the prototype.
I don't see what you're trying to show me, I don't see anything
strange in here: `foo' is simply re-declared, it had one type
in the first case, and a different type in the second case (it's
allowed for identifiers that have linkage).

It's similar as in my first example a few pages up: both `a' and
`b' start with the same incomplete type, but then each identifier
is re-declared (in different ways) and acquires a different (complete)
type (actually: composite type). The initial and final types are
different.

(It's impossible to make similar parallel for structs, because
their completion is one-way only - a single struct definition
automatically completes all identifiers in the same scope.)
A type can be incomplete at one point in the source file and then complete
later on.
Hmmm.... I don't have an answer to that, but I strongly disagree.
I think that an object type can either be complete or incomplete,
but never both.

"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)." (6.2.5p1)

For the first thing, I think the word "partitioned" determines it.
For another, a type cannot *fully* describe an object and lack information
about its size at the same time.

When the Standard says "a type is completed", I think it means a new
type is created. I have grep'ed it for "complete" (to find "incomplete",
"complete", "completed", "completely" etc.), and I haven't found anything
to suggest unambiguously anything opposite.

For the last thing: "The presence of a struct-declaration-list
in a struct-or-union-specifier declares a new type, within a
translation unit." (6.7.2.1p7), therefore I think that in:
struct s;
struct s {...};
the types must be different (second type is a *new* type).
If one is incomplete, the other complete, then they're different types,
I thought that was pretty logical. Could you give some example, or
a reference (c&v), please?

The wording of the standard you quote above depends on this. A type can
be incomplete at one point in the source code and complete later on. "The
same type" here is simply the opposite of "distinct types". Consider {
struct foo { int x } a;
} {
struct foo { int x } b;
} a and b have 2 distinct types here, and they are incompatible.
Yes, so what?
Given your
example > /* 1 */ struct mystruct object;
> /* 2 */ struct mystruct { /*...*/ };


[a small "enhancement":]

/* 1 */ struct mystruct object1;
/* 1a */ struct mystruct object1a;
/* 2 */ struct mystruct { /*...*/ } object2;
the fact that the 2 lines refer to the same type means that the completing
of the type in the second line affects the type of object because they are
the same type. So after line 2 (sizeof object) is valid, which it wouldn't
be if they weren't the same type. I think that is all it is saying.


In my view, `object' changes its type[*] after the second
declaration, that's why sizeof object is okay after the second
declaration. However, both declarations declare distinct types.
[*] not because the declarations are "the same type", but because
the first declaration with the same tag is in the same scope, and
this case is covered by the first quote (I think).
# [#3] All declarations of structure, union, or enumerated
# types that have the same scope and use the same tag declare
# the same type.

Following the letter, the above excerpt concerns only (type,
not object) declarations 1 and 2, and not 1a, because 1a is not
a declaration of a type (because previous declaration is visible
- cf. 6.7.2.3p7,8), it merely specifies the same type as in 1.
Both type declarations 1 and 2 have the same scope and the same
tag, therefore (according to the quote) they declare the same
type. (I think that's clear - my understanding and deduction skills
are still in order... right?).

1. I don't agree with that (which I have outlined above).
2. I don't see any need for that. Can you show what would change
if that particular sentence was not there?
Maybe it's just an error in the Standard, or maybe I need a life.

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 14 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.