Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
The error is:
error: array type has incomplete element type 'struct scenet'
struct scenet (*child)[];
^~~~~
Is there any way to fix this, or is it not possible?
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
The error is:
error: array type has incomplete element type 'struct scenet'
struct scenet (*child)[];
^~~~~
Is there any way to fix this, or is it not possible?
(This comes from generated code. Idiomatic C would use a T* here rather than T(*)[], but that is not an option. Other compilers like tcc, DMC and mine have no problem with it.)
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
The error is:
error: array type has incomplete element type 'struct scenet'
struct scenet (*child)[];
^~~~~
This looks like a bug to me. There is on reason why an
incomplete array type (a pointer to which /is/ allowed!)
should be constrained to have a complete element.
struct scenet (*child)[];
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can
anyone tell me why it was removed? With it gone, I'm not sure it is
still considered an incomplete type.
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
The error is:
error: array type has incomplete element type 'struct scenet'
struct scenet (*child)[];
^~~~~
Is there any way to fix this, or is it not possible?
(This comes from generated code. Idiomatic C would use a T* here
rather than T(*)[], but that is not an option. Other compilers like
tcc, DMC and mine have no problem with it.)
On Thu, 23 Jan 2025 1:05:25 +0000, James Kuyper wrote:
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is
incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can
anyone tell me why it was removed? With it gone, I'm not sure it is
still considered an incomplete type.
It seems to have been moved to N3047 6.2.5(25): "[...] A structure or
union type of unknown content (as described in 6.7.2.3) is an incomplete type. [...]" (see here: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf#page=57).
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can anyone tell me why it was removed? [...]
On Thu, 23 Jan 2025 1:05:25 +0000, James Kuyper wrote:
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is
incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can
anyone tell me why it was removed? With it gone, I'm not sure it is
still considered an incomplete type.
It seems to have been moved to N3047 6.2.5(25): "[...] A structure or
union type of unknown content (as described in 6.7.2.3) is an incomplete type. [...]" (see here: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf#page=57).
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can
anyone tell me why it was removed? With it gone, I'm not sure it is
still considered an incomplete type.
Ignoring for the moment the fact that it's not permitted, why do you
want to do that? In C code, people usually use pointers to the first
element of an array rather than pointers to arrays. However, it
sometimes is a good idea to have a pointer to an array, because that
makes the length of the array part of the pointer type, which can be
used to check the validity of the code that uses that pointer to access
the elements of the array. But in this case, the length of the array is unspecified, so there's no such benefit.
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is
incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different from
the array version (actually, the code from my compiler is identical).
However, that sentence disappeared in n3047.pdf, dated 2022-08-04. Can
anyone tell me why it was removed? With it gone, I'm not sure it is
still considered an incomplete type.
Ignoring for the moment the fact that it's not permitted, why do you
want to do that? In C code, people usually use pointers to the first
element of an array rather than pointers to arrays. However, it
sometimes is a good idea to have a pointer to an array, because that
makes the length of the array part of the pointer type, which can be
used to check the validity of the code that uses that pointer to access
the elements of the array. But in this case, the length of the array is
unspecified, so there's no such benefit.
I said the code is generated, which means the original language uses a pointer-to-array at that spot.
That is safer, as you can't mistakenly index a pointer which happens to
be a reference to a single instance.
In any case, you should surely be able to choose a T(*)[] type over T*
if you want, but apparently not inside a self-referential struct.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member.
On Thu, 23 Jan 2025 10:54:10 +0000, bart wrote:
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member.
No, because there is no pointer arithmetic involved in processing that declaration.
On 1/23/2025 4:54 AM, bart wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is
incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different
from the array version (actually, the code from my compiler is
identical).
Difference is, in this case, "sizeof(struct scenet)" is not relevant to "sizeof(struct scenet *)".
Formally, with the parenthesis and array, the size of the struct is considered relevant (even if not strictly so), but is also unknown at
that point.
This seems like obscure edge case territory.
Alas, if I could have my way, I might define a simplified subset which
drops some of these sorts of edge cases (the form with parenthesis would simply become disallowed), but, likely, this wouldn't amount to much.
Say, for a language that is:
Mostly backwards compatible with existing C code;
Allows for a smaller and simpler compilers;
Uses some C# like rules to eliminate the need for checking for typedefs
to parse stuff.
Though, one can't go entirely over to C# like behavior if one still
wants to support traditional separate compilation (so one would still
have a need for things like function prototypes, header files, and a traditional preprocessor).
But, then one would basically just end up with C but with people being confused about why things like "unsigned x;" no longer work (making it
kinda moot).
And, most people continue to swear by GCC and Clang, unconcerned with
their multi MLOC codebases, and the overly long time it takes to
recompile the compiler from source...
Granted, my existing compiler is a bit bigger; sadly, its code footprint
is more on par with Quake3, and its memory footprint generally a bit
steep (well, if one wants to run it on an FPGA board with 128MB of total RAM; ideally one wants to keep the memory footprint needed to compile a moderate size program in under around 50MB or so; which is an epic fail
for my compiler as it is...).
And, as-is, compiling stuff takes a painfully long time on a 50MHz CPU
(even a moderately small program might take several minutes or more).
Yet childp is fine, but childa is a gcc compiler error. Why is that?
On Fri, 24 Jan 2025 00:37:27 +0000, bart wrote:[snipped context restored]
struct scenet *childp;
struct scenet (*childa)[];
};
Yet childp is fine, but childa is a gcc compiler error. Why is that?
Because it needs to know the size of the type to work out the function type’s calling convention.
On Fri, 24 Jan 2025 00:37:27 +0000, bart wrote:
Yet childp is fine, but childa is a gcc compiler error. Why is that?
Because it needs to know the size of the type to work out the function type’s calling convention.
On 23/01/2025 20:58, BGB wrote:
On 1/23/2025 4:54 AM, bart wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is >>>> incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace >>>> of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different
from the array version (actually, the code from my compiler is
identical).
Difference is, in this case, "sizeof(struct scenet)" is not relevant
to "sizeof(struct scenet *)".
No, both of these need to know the size of the struct when accessing the i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic
on the whole pointer-to-array, since the array size is zero. But doing (x->childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
Formally, with the parenthesis and array, the size of the struct is
considered relevant (even if not strictly so), but is also unknown at
that point.
This seems like obscure edge case territory.
It's a 'pointer to array'; it might be uncommon in C (because of its
fugly syntax), but it hs hardly obscure!
Alas, if I could have my way, I might define a simplified subset which
drops some of these sorts of edge cases (the form with parenthesis
would simply become disallowed), but, likely, this wouldn't amount to
much.
T(*)[] is a perfectly valid type; there is no reason to exclude it from struct members.
It is unambiguous in my original language, and can also be in C.
Say, for a language that is:
Mostly backwards compatible with existing C code;
Allows for a smaller and simpler compilers;
Uses some C# like rules to eliminate the need for checking for
typedefs to parse stuff.
Though, one can't go entirely over to C# like behavior if one still
wants to support traditional separate compilation (so one would still
have a need for things like function prototypes, header files, and a
traditional preprocessor).
But, then one would basically just end up with C but with people being
confused about why things like "unsigned x;" no longer work (making it
kinda moot).
And, most people continue to swear by GCC and Clang, unconcerned with
their multi MLOC codebases, and the overly long time it takes to
recompile the compiler from source...
Yeah. I can choose to run my compiler from source each time it is
invoked; you barely notice the difference! (It adds 70-80ms.)
This cuts no ice here however.
Granted, my existing compiler is a bit bigger; sadly, its code
footprint is more on par with Quake3, and its memory footprint
generally a bit steep (well, if one wants to run it on an FPGA board
with 128MB of total RAM; ideally one wants to keep the memory
footprint needed to compile a moderate size program in under around
50MB or so; which is an epic fail for my compiler as it is...).
And, as-is, compiling stuff takes a painfully long time on a 50MHz CPU
(even a moderately small program might take several minutes or more).
You can't cross-compile on a PC?
No, both of these need to know the size of the struct when accessing the i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic
on the whole pointer-to-array, since the array size is zero. But doing (x->childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is
incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace
of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different from
the array version (actually, the code from my compiler is identical).
On 23/01/2025 20:58, BGB wrote:
On 1/23/2025 4:54 AM, bart wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is >>>> incomplete144) until immediately after the closing brace of the list
defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace >>>> of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different
from the array version (actually, the code from my compiler is
identical).
Difference is, in this case, "sizeof(struct scenet)" is not relevant
to "sizeof(struct scenet *)".
No, both of these need to know the size of the struct when accessing the i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic
on the whole pointer-to-array, since the array size is zero. But doing (x->childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace of
the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
On 24/01/2025 01:51, bart wrote:
This is one of these cases where the C language /could/ have been
No, both of these need to know the size of the struct when accessing the
i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic
on the whole pointer-to-array, since the array size is zero. But doing
childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
defined to allow incomplete types to be used. But the language
definition (the standards) does not allow it.
1. Should future C standards be modified to be more lenient in the code
the accept? Was there a good reason for these limitations, and is that reason still valid?
On 2025-01-24, David Brown <david.brown@hesbynett.no> wrote:
On 24/01/2025 01:51, bart wrote:
This is one of these cases where the C language /could/ have been
No, both of these need to know the size of the struct when accessing the >>> i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic >>> on the whole pointer-to-array, since the array size is zero. But doing
childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
defined to allow incomplete types to be used. But the language
definition (the standards) does not allow it.
It does; the implementation can issue a required diagnostic,
and keep chugging along. The behavior becomes undefined, but
the same implementation can provide its own definition:
like such that when the type is completed by the time it
matters, it's all good.
The language definition only does not allow the implementation to be
called conforming if it doesn't diagnose the usage, and doesn't allow
the program's behavior to be well-defined ISO C.
1. Should future C standards be modified to be more lenient in the code
the accept? Was there a good reason for these limitations, and is that
reason still valid?
In this particular matter, GNU C++ accepts the code. If that happens to
be because of how ISO C++ is defined, then that carries substantial
weight. Why should C require a diagnostic in something that C++
allows to pass. (C++, whose C-like subset is touted as a "safer C"!)
Speaking of which, Bart never responded to the workaround I found,
namely that g++ accepts his code.
On 1/23/2025 6:51 PM, bart wrote:
On 23/01/2025 20:58, BGB wrote:
On 1/23/2025 4:54 AM, bart wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the type is >>>>> incomplete144) until immediately after the closing brace of the list >>>>> defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing brace >>>>> of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
The struct is incomplete, but it still knows how to do pointer
arithmetic with that member. The calculation is not that different
from the array version (actually, the code from my compiler is
identical).
Difference is, in this case, "sizeof(struct scenet)" is not relevant
to "sizeof(struct scenet *)".
No, both of these need to know the size of the struct when accessing the
i'th element:
....
struct scenet *childp;
struct scenet (*childa)[];
};
The only thing you can't do with x->childa is perform pointer arithmetic
on the whole pointer-to-array, since the array size is zero. But doing
childa)[i] should be fine.
As is clear since other compilers (excluding those that lavishly copy
gcc's behaviour) have no problem with it.
The problem is not what you can do with the pointer, but the alignment
and representation of the pointer itself. Those are uniquely determined
for childp by the fact that it's a pointer to a struct type, regardless
of the content of that type (6.2.5p33). The alignment and representation
of childa, on the other hand, could depend upon the content of struct
scenet (in particular, the size of that struct type). It needs to know
those requirements, in order to complete the definition of struct
scenet. That's not an insoluble problem: just choose an alignment and representation for childa that allows a pointer to the entire struct to
have that same alignment and representation - but the standard chose not
to mandate that it be solved.
If you've never tried to create a compiler for a platform where it makes sense to have pointers to object types with different alignment and representations, depending upon the type that they point at, you
probably have no idea what would be involved in solving that problem (I certainly don't).
On 2025-01-24, David Brown <david.brown@hesbynett.no> wrote:...
This is one of these cases where the C language /could/ have been
defined to allow incomplete types to be used. But the language
definition (the standards) does not allow it.
It does; the implementation can issue a required diagnostic,
and keep chugging along. The behavior becomes undefined, but
the same implementation can provide its own definition:
like such that when the type is completed by the time it
matters, it's all good.
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or function
type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace of
the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not related specifically to recursive structures. It applies to arrays of
incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
The case of the recursive structure is special only in a sense that it's
o.k. in C++, because [unlike C] in C++ struct considered complete within
its own body.
Is it just because such pointers HAVE to work, otherwise
self-referential structs become impossible?
On 24/01/2025 14:37, Michael S wrote:
This is a pointer to an incomplete type. Attempts to do ++ptr for
example will fail later on if that struct has not yet been defined.
So why not the same for the pointer-to-array versions?
It just doesn't make sense.
The case of the recursive structure is special only in a sense that it's
o.k. in C++, because [unlike C] in C++ struct considered complete within
its own body.
For non-recursive, you can choose to declare the pointer-to-array after
the struct has been fully defined.
On 2025-01-26, bart <bc@freeuk.com> wrote:
On 24/01/2025 14:37, Michael S wrote:
This is a pointer to an incomplete type. Attempts to do ++ptr for
example will fail later on if that struct has not yet been defined.
So why not the same for the pointer-to-array versions?
It just doesn't make sense.
You already know that GNU C++ silently accepts it, so this is
beating a dead horse.
Your situation is this:
struct incomplete {
struct incomplete (*parray)[];
};
If we make a pointer to a struct rather than array,
it's the same kind of problem:
struct incomplete {
struct nested_incomplete {
struct incomplete memb;
} *pstruct;
};
In both cases, we have a pointer to something which
has an element, or member, of the incomplete type of
the outer struct which is to contain the pointer.
If the array version should work, so should the
struct version.
The case of the recursive structure is special only in a sense that it's >>> o.k. in C++, because [unlike C] in C++ struct considered complete within >>> its own body.
For non-recursive, you can choose to declare the pointer-to-array after
the struct has been fully defined.
If a C++ struct is complete within its own body, that means this should
be possible:
struct foo {
struct foo x;
int y;
};
On 24/01/2025 14:37, Michael S wrote:
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or
function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace
of the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not
related specifically to recursive structures. It applies to arrays
of incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
I don't think anyone has yet explained why that is an error (other
than C says it is), but not this:
struct bar *ptr;
This is a pointer to an incomplete type. Attempts to do ++ptr
for example will fail later on if that struct has not yet been
defined.
So why not the same for the pointer-to-array versions?
bart <bc@freeuk.com> writes:
On 24/01/2025 14:37, Michael S wrote:
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or
function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace
of the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not
related specifically to recursive structures. It applies to arrays
of incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
I don't think anyone has yet explained why that is an error (other
than C says it is), but not this:
struct bar *ptr;
This is a pointer to an incomplete type. Attempts to do ++ptr
for example will fail later on if that struct has not yet been
defined.
So why not the same for the pointer-to-array versions?
The question you should be asking is why did the original C
standards body make the rule they did?
The answer might be because this exception to a simple and
general rule is almost never useful, and never necessary.
Considering that it has been 35 years since that original rule
was made, and 2025 is the first time the question has come up,
the indications are that the original decision was a good one.
bart <bc@freeuk.com> writes:
On 24/01/2025 14:37, Michael S wrote:
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or
function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace
of the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not
related specifically to recursive structures. It applies to arrays
of incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
I don't think anyone has yet explained why that is an error (other
than C says it is), but not this:
struct bar *ptr;
This is a pointer to an incomplete type. Attempts to do ++ptr
for example will fail later on if that struct has not yet been
defined.
So why not the same for the pointer-to-array versions?
The question you should be asking is why did the original C
standards body make the rule they did?
The answer might be because this exception to a simple and
general rule is almost never useful, and never necessary.
Considering that it has been 35 years since that original rule
was made, and 2025 is the first time the question has come up,
the indications are that the original decision was a good one.
On 1/29/25 5:59 AM, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
On 24/01/2025 14:37, Michael S wrote:
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or
function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace
of the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not
related specifically to recursive structures. It applies to arrays
of incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
I don't think anyone has yet explained why that is an error (other
than C says it is), but not this:
struct bar *ptr;
This is a pointer to an incomplete type. Attempts to do ++ptr
for example will fail later on if that struct has not yet been
defined.
So why not the same for the pointer-to-array versions?
The question you should be asking is why did the original C
standards body make the rule they did?
My guess is that it makes the simplest implementation of a C compiler
much more complicated. While I don't think it has been explicited
stated, one goal the original language, and apparently kept by the
Standards Comittee, has been to make the language fairly simple to
proceess to get working code. To optimize to make fast, might take
more work, but to make your first complier for a system should be
straight forward. I believe a C compiler can still be done with a
single pass through the source code, with limited look ahead, and only
the final "link" step needs to be able to handle large chunks of the
program.
Allowing the pointer to array time to be based on an incomplete type
might make this goal harder.
On 29/01/2025 10:59, Tim Rentsch wrote:
bart <bc@freeuk.com> writes:
On 24/01/2025 14:37, Michael S wrote:
On Thu, 23 Jan 2025 10:54:10 +0000
bart <bc@freeuk.com> wrote:
On 23/01/2025 01:05, James Kuyper wrote:
On 2025-01-22, bart <bc@freeuk.com> wrote:
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
6.7.6.2p2: "The element type shall not be an incomplete or
function type."
I have many draft versions of the C standard. n2912.pdf, dated
2022-06-08, says in 6.7.2.1.p3 about struct types that "... the
type is incomplete144) until immediately after the closing brace
of the list defining the content, and complete thereafter."
Therefore, struct scenet is not a complete type until the closing
brace of it's declaration.
Wouldn't this also be the case here:
struct scenet *child;
};
Just to point out if it was not said already: the problem is not
related specifically to recursive structures. It applies to arrays
of incomplete types in all circumstances.
struct bar;
struct bar (*bag)[]; // error
typedef struct bar (*bat)[]; // error
I don't think anyone has yet explained why that is an error (other
than C says it is), but not this:
struct bar *ptr;
This is a pointer to an incomplete type. Attempts to do ++ptr
for example will fail later on if that struct has not yet been
defined.
So why not the same for the pointer-to-array versions?
The question you should be asking is why did the original C
standards body make the rule they did?
The answer might be because this exception to a simple and
general rule is almost never useful, and never necessary.
Well, you never see such a thing in use, certainly. I wonder why
that is!
When a language outlaws some particular construction, forcing
people to stick to a particular idiom (the common use of a T* type
to work with pointers and arrays instead of the more sensible and
safer T(*)[]), then clearly you're not going to see such uses in
the field.
Although there are really two parts to it: use of T(*)[]
generally (outside of self-referential structs) is allowed, but
that is still rare, presumably because the syntax is too unwieldy.
Or people simply don't know about it, since everyone uses T*.
Considering that it has been 35 years since that original rule
was made, and 2025 is the first time the question has come up,
the indications are that the original decision was a good one.
We don't know that. Perhaps it comes up all the time, people
realise they can't use such a construct, and use a different
approach.
Gcc 14.1 gives me an error compiling this code:
struct vector;
struct scenet;
struct vector {
double x;
double y;
double z;
};
struct scenet {
struct vector center;
double radius;
struct scenet (*child)[];
};
The error is:
error: array type has incomplete element type 'struct scenet'
struct scenet (*child)[];
^~~~~
Is there any way to fix this, or is it not possible?
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 1,010 |
Nodes: | 10 (0 / 10) |
Uptime: | 31:11:16 |
Calls: | 13,187 |
Calls today: | 1 |
Files: | 186,574 |
D/L today: |
199 files (49,090K bytes) |
Messages: | 3,321,572 |