Question about incomplete array element types

P

Paul F. Dietz

Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }


Paul Dietz
(e-mail address removed)
 
C

Chris Torek

Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }

(You should make it "int main()" and add a "return 0;" statement at
the end too, of course; and you need to #include <stdio.h>; but I
assume you have already done this. :) )

I was going to say "yes"; then I checked the wording in the standard.

The first line creates the type "struct foo" as an incomplete type.
The second refers back to it and declares "p" as a pointer to "array
10 of that incomplete type." This is where the problem appears to
lie: the Standard says that an array can only have an object type
as its element type. An incomplete type is not an object type,
so "array 10 of <incomplete>" is not a valid array type.

Of course, there seems to be no particular reason to forbid pointers
to "array N of <incomplete>", especially since C *does* allow
pointers to incomplete types, including the type "pointer to array
? of T" for some object type T:

typedef some_object_type_here T;
extern T (*p2)[]; /* valid */

When the size is missing, as in this case, the array itself is an
incomplete type, so "p2" is a pointer to an incomplete type.
(Similarly, "void" is an incomplete type that can never be completed,
so "void *p3" makes p3 a pointer to an incomplete type.)

Still, this is what the standard says, however wrongheaded it might
be, so the second line appears to violate a constraint and require
a diagnostic. "gcc -ansi -pedantic" seems to agree with me, which
gives me additional confidence that I have not misinterpreted the
wording. :)
 
R

Ravi Uday

Paul F. Dietz said:
Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }


Paul Dietz
(e-mail address removed)

Yes, except that *main* returns *int* so return - 0 / EXIT_SUCCESS/ EXIT_FAILURE.

Even better -
struct foo {
int bar;
int baz; };

struct foo (*p)[10]; /* Pointer to array of 10 foo structures */

int main() {
printf("%d\n", sizeof(*p));
return 0;

}
 
K

Kevin Easton

Chris Torek said:
Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }

(You should make it "int main()" and add a "return 0;" statement at
the end too, of course; and you need to #include <stdio.h>; but I
assume you have already done this. :) )

I was going to say "yes"; then I checked the wording in the standard.

The first line creates the type "struct foo" as an incomplete type.
The second refers back to it and declares "p" as a pointer to "array
10 of that incomplete type." This is where the problem appears to
lie: the Standard says that an array can only have an object type
as its element type. An incomplete type is not an object type,
so "array 10 of <incomplete>" is not a valid array type.

Of course, there seems to be no particular reason to forbid pointers
to "array N of <incomplete>", especially since C *does* allow
pointers to incomplete types, including the type "pointer to array
? of T" for some object type T:

typedef some_object_type_here T;
extern T (*p2)[]; /* valid */

When the size is missing, as in this case, the array itself is an
incomplete type, so "p2" is a pointer to an incomplete type.
(Similarly, "void" is an incomplete type that can never be completed,
so "void *p3" makes p3 a pointer to an incomplete type.)

Still, this is what the standard says, however wrongheaded it might
be, so the second line appears to violate a constraint and require
a diagnostic. "gcc -ansi -pedantic" seems to agree with me, which
gives me additional confidence that I have not misinterpreted the
wording. :)

That must be a newer version of gcc than 2.95.2 - with it, I get some
quite strange behaviour. The program:

#include <stdio.h>

struct foo (*p)[10];
struct foo { int a; double b; };

int main()
{
printf("%lu\n", (unsigned long) sizeof (*p));

return 0;
}

fails to compile, as you might expect, but the error is on the printf
line - "sizeof applied to an incomplete type". However, the following
program:

#include <stdio.h>

struct foo (*p)[10];
struct foo { int a; double b; };
struct foo a[10];

int main()
{
printf("%lu\n", (unsigned long) sizeof (*p));

return 0;
}

Compiles without any warnings or errors (-Wall -ansi -pedantic), and
prints "120". It seems that merely "thinking" about the type
(struct foo [10]) after the type (struct foo) is completed is enough to
"fix" it. It seems that 2.95.2 is therefore not a conforming compiler.

- Kevin.
 
Z

Zoran Cutura

Ravi Uday said:
Paul F. Dietz said:
Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }


Paul Dietz
(e-mail address removed)

Yes, except that *main* returns *int* so return - 0 / EXIT_SUCCESS/ EXIT_FAILURE.

Even better -

But it changes the meaning of the code and does not include the problem
me thinks the OP was heading at.
struct foo {
int bar;
int baz; };

struct foo (*p)[10]; /* Pointer to array of 10 foo structures */

Now struct foo isn't incomplete and struct foo [10] is neither.

The thing is that we can have a pointer to an incomlete type, but can we
have a pointer to an array of incomplete type and the answer was given
by Chris Torek in his parallel post.
int main() {
printf("%d\n", sizeof(*p));
return 0;

}

Naturally one would write it like you suggest, but when you are hiding
the implementation/definition of the struct from for instance the user
of a library, this is not what you want to do.
 
D

Dan Pop

In said:
Is the following legal C?

struct foo;
struct foo (*p)[10]; /* Pointer to array of 10 foo structures */
struct foo { int bar; int baz; };
main() { printf("%d\n", sizeof(*p)); }

(You should make it "int main()" and add a "return 0;" statement at
the end too, of course; and you need to #include <stdio.h>; but I
assume you have already done this. :) )

I was going to say "yes"; then I checked the wording in the standard.

The first line creates the type "struct foo" as an incomplete type.
The second refers back to it and declares "p" as a pointer to "array
10 of that incomplete type." This is where the problem appears to
lie: the Standard says that an array can only have an object type
as its element type. An incomplete type is not an object type,
so "array 10 of <incomplete>" is not a valid array type.

Not at that point (and no diagnostic is required, anyway). However:

22 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.

Since the type is completed by the time sizeof(*p) is evaluated,
everything should be OK.

Dan
 

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

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top