 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Minkoo Seo Guest
|
Posted: Sat Jul 16, 2005 10:26 am Post subject: incomplete type revisited. |
|
|
I know that some people are talking about more complex problems
than I want to ask with regard to incomplete type. But, let me
talk about three fundamental issues:
1) Is incomplete type specification related to C++ only?
see the following snippet.
[root@protos tmp]# cat test.c
#include <stdio.h>
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
printf("%dn", foo[i]);
}
return 0;
}
[root@protos tmp]# gcc test.c
[root@protos tmp]# ./a.out
0
1
2
[root@protos tmp]# cat test.cpp
#include
using namespace std;
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
cout << foo[i] << endl;
}
return EXIT_SUCCESS;
}
[root@protos tmp]# gcc test.cpp
test.cpp: In function 'int main()':
test.cpp:11: error: type mismatch with previous external decl of 'int
foo []'
test.cpp:6: error: previous external decl of 'int foo [3]'
[root@protos tmp]# gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.0 20050519 (Red Hat 4.0.0-
[root@protos tmp]# g++ -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.0 20050519 (Red Hat 4.0.0-
[root@protos tmp]#
As you can see, extern int foo[] succeeds in test.c, but throws an
error in test.cpp. Does that mean 'incomplete type error' is
related to C++ only?
2) Why the compiler can't find the size information?
See the code.
[root@protos tmp]# cat test.cpp
#include
using namespace std;
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
cout << foo[i] << endl;
}
return EXIT_SUCCESS;
}
[root@protos tmp]# gcc test.cpp
test.cpp: In function 'int main()':
test.cpp:11: error: type mismatch with previous external decl of 'int
foo []'
test.cpp:6: error: previous external decl of 'int foo [3]'
Here, I know that extern in foo[] is invalid due to C++
specification. IMHO, however, everyone knows that extern int foo[]
actually means the in foo[3] array defined globally. That means
that the size information is known when we see extern int foo[].
Let me think from the perspective of a compiler. 'int foo[3]' precedes
'extern int foo[]' in the code. So, it is manifest that any compiler
will see the int foo[3] definition before it sees the 'extern int
foo[]'.
That means that the extern int foo[] is complete; it's size information
is known in advance. If the lines of my reasoning is true, why does the
compiler raise an error?
3) Why is the size information needed?
Let's think about the code in item 2. In the code, the size of foo
array is 3. And I also hardcoded the size of array, 3, in the for
loop: i < 3. That means the size information is not needed because
C/C++ programmers are responsible for the specifying correct size
information like the aforementioned code.
C/C++ does not perform boundary check like JAVA or C#, but the C++
specification requires that the size information should be informed to
the compiler. Why the specification postulate that the unneeded
information should be provided?
Regards,
Minkoo Seo.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Mon Jul 18, 2005 2:03 pm Post subject: Re: incomplete type revisited. |
|
|
Minkoo Seo wrote:
| Quote: | I know that some people are talking about more complex
problems than I want to ask with regard to incomplete type.
But, let me talk about three fundamental issues:
1) Is incomplete type specification related to C++ only?
|
No. Incomplete types are present in both C and C++. I rather
believe that the intent in C++ is for them to work the same as
in C, at least with regards to arrays. The actual wording in
the two standards differs, however, and neither can be said to
be a model of clarity.
| Quote: | see the following snippet.
[root@protos tmp]# cat test.c
#include
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
printf("%dn", foo[i]);
}
return 0;
}
[root@protos tmp]# gcc test.c
[root@protos tmp]# ./a.out
0
1
2
[root@protos tmp]# cat test.cpp
#include
using namespace std;
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
cout << foo[i] << endl;
}
return EXIT_SUCCESS;
}
[root@protos tmp]# gcc test.cpp
test.cpp: In function 'int main()':
test.cpp:11: error: type mismatch with previous external decl of 'int
foo []'
test.cpp:6: error: previous external decl of 'int foo [3]'
[root@protos tmp]# gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.0 20050519 (Red Hat 4.0.0-
[root@protos tmp]# g++ -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--enable-checking=release --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-libgcj-multifile
--enable-languages=c,c++,objc,java,f95,ada --enable-java-awt=gtk
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre
--host=i386-redhat-linux
Thread model: posix
gcc version 4.0.0 20050519 (Red Hat 4.0.0-
[root@protos tmp]#
As you can see, extern int foo[] succeeds in test.c, but
throws an error in test.cpp. Does that mean 'incomplete type
error' is related to C++ only?
|
My first reaction was that this was a simple compiler bug. A
test with Sun CC also showed that the code compiled and worked
as expected in C++.
On the other hand, every version of g++ I tried gave the same
error message. From what I understand, g++ underwent a major
rewrite between versions 2.95.3 and 3.0. Enough of a rewrite to
suppose that if the behavior is the same in both 2.95.2 and in
more recent versions, it is intentional. And on checking the
standard (§8.3.4/1), there is a sentence: "The type
'derived-declarator-type-list array of N of T,' is a different
type from the type 'derived-declarator-type-list array of
unknown bound of T.'" In addition, in §3.9/7, it says "The
declared type of an array object might be an array of unknown
size and therefore be incomplete at one point in a translation
unit and complete later on; the array types at those two points
('array of unknown boudn of T' and 'array of N T') are different
types."
On the other hand, there is no doubt that:
extern int foo[] ;
// ...
int foo[ 3 ] ;
is legal. The only difference here is in the order in which the
compilers see the declarations.
Traditionnally, and I believe that this is probably the intent
as well, compilers have maintained a list of the information
concerning the variable as they went along. If the total
information included the dimension data, the type was complete;
if not, it wasn't. Regretfully, the actual wording of the
standard says that the type may be completed *later*, not that
it may be completed *elsewhere*. Interestingly enough, the C
standard shares the same problem (§6.2.5/22): "An array type of
unknown size is an incomplete type. It is completed, for an
identifier of that type, but specifying the size *in* *a*
*later* declaration." Taken (too ?) literally, there is a
problem in the C code as well.
My immediate reaction is that this is just a case of sloppy
wording, and that the real intention must be that once a type is
complete, it remains complete, even if later declarations would
only be of an incomplete type. But I have to admit that the
reason that this is "obvious" to me is 25 years of experience
with C and C++ compilers, and not any words I can find in the
standard.
[...]
| Quote: | 3) Why is the size information needed?
Let's think about the code in item 2. In the code, the size of
foo array is 3. And I also hardcoded the size of array, 3, in
the for loop: i < 3. That means the size information is not
needed because C/C++ programmers are responsible for the
specifying correct size information like the aforementioned
code.
C/C++ does not perform boundary check like JAVA or C#, but the
C++ specification requires that the size information should be
informed to the compiler. Why the specification postulate that
the unneeded information should be provided?
|
The problem isn't that the size information is needed. The
error messages you are seeing are for the declaration. The
declaration is for an incomplete type. A previous declaration
was for a complete type. Incomplete types and complete types
are different types. While an incomplete type can be completed
(and effectively changes type), the standards (both C and C++)
use the word "later" when talking about this. Two
interpretations are possible:
-- once the type is complete, it remains complete, even through
a declaration which would be for an incomplete type, and
-- once the type is complete, it can no longer be declared
incomplete, since this would have the effect of changing a
complete type into an incomplete type, a transformation for
which the standard makes no provisions.
Personally, only the first interpretation makes any real sense
to me. But apparently, the authors of g++ disagree, and have
implemented the second. Interestingly enough, in this case,
they also disagree with the authors of gcc, although the rule is
pretty much the same in the two languages. Still, the wording
seems ambiguous enough to me that I think a DR would be in
order.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Jul 19, 2005 9:13 am Post subject: Re: incomplete type revisited. |
|
|
For what it's worth, Comeau compiles
int foo[3];
int main() { extern int foo[]; }
without complaint.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Minkoo Seo Guest
|
Posted: Tue Jul 19, 2005 9:30 am Post subject: Re: incomplete type revisited. |
|
|
Please let me clarify the third point.
[...]
| Quote: | 3) Why is the size information needed?
Let's think about the code in item 2. In the code, the size of
foo array is 3. And I also hardcoded the size of array, 3, in
the for loop: i < 3. That means the size information is not
needed because C/C++ programmers are responsible for the
specifying correct size information like the aforementioned
code.
C/C++ does not perform boundary check like JAVA or C#, but the
C++ specification requires that the size information should be
informed to the compiler. Why the specification postulate that
the unneeded information should be provided?
The problem isn't that the size information is needed. The
error messages you are seeing are for the declaration. The
declaration is for an incomplete type. A previous declaration
was for a complete type. Incomplete types and complete types
are different types. While an incomplete type can be completed
(and effectively changes type), the standards (both C and C++)
use the word "later" when talking about this. Two
interpretations are possible:
-- once the type is complete, it remains complete, even through
a declaration which would be for an incomplete type, and
-- once the type is complete, it can no longer be declared
incomplete, since this would have the effect of changing a
complete type into an incomplete type, a transformation for
which the standard makes no provisions.
Personally, only the first interpretation makes any real sense
to me. But apparently, the authors of g++ disagree, and have
implemented the second. Interestingly enough, in this case,
they also disagree with the authors of gcc, although the rule is
pretty much the same in the two languages. Still, the wording
seems ambiguous enough to me that I think a DR would be in
order.
[...] |
What I am trying to make clear here is the intention of
incomplete type. AFAIK, there are two kinds of incomplete
type that can occur.
1) struct a; // or class a;
2) int array_name[];
The meaning of incomplete type is quite clear when we talk about
the first one, 'struct a', because that's a kind of definition
which lacks the actual definition.
However, incompleteness with regard to the second one,
int array_name[], does not make sense to me. The reason why the
second one is incomplete is that the size of the array is unknown.
As I mentioned previously, however, compilers do not need to know the
'size' of an array in C/C++, because keeping size information is
entirely up to programmers.
Why the second type of declaration was sentenced to be incomplete
in the standard?
Regards,
Minkoo Seo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Tue Jul 19, 2005 9:35 am Post subject: Re: incomplete type revisited. |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote in message news:<1121686092.664821.234750 (AT) g44g2000cwa (DOT) googlegroups.com>...
| Quote: | Minkoo Seo wrote:
I know that some people are talking about more complex
problems than I want to ask with regard to incomplete type.
But, let me talk about three fundamental issues:
1) Is incomplete type specification related to C++ only?
No. Incomplete types are present in both C and C++. I rather
believe that the intent in C++ is for them to work the same as
in C, at least with regards to arrays. The actual wording in
the two standards differs, however, and neither can be said to
be a model of clarity.
see the following snippet.
[snip]
[root@protos tmp]# cat test.cpp
#include
using namespace std;
int foo[3] = {0, 1, 2};
int main(void)
{
int i;
extern int foo[];
for (i = 0; i < 3; i++)
{
cout << foo[i] << endl;
}
return EXIT_SUCCESS;
}
[snip]
As you can see, extern int foo[] succeeds in test.c, but
throws an error in test.cpp. Does that mean 'incomplete type
error' is related to C++ only?
My first reaction was that this was a simple compiler bug. A
test with Sun CC also showed that the code compiled and worked
as expected in C++.
[snip] |
If you put "extern int foo[3] = {0, 1, 2};" into another file, then
g++ had no problem. If there is a problem of g++, I think the problem
is the interpretation of "extern".
g++ looks for the foo[] definition within the file and reports the
type mismatch between foo[] and foo[3]. If g++ left the look-up to the
linker, then g++ would not have any problem. I do not know what the
Standard says about this.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Jul 19, 2005 11:29 am Post subject: Re: incomplete type revisited. |
|
|
In article <49c1da0b.0507181842.36758207 (AT) posting (DOT) google.com>, Tokyo Tomy
<hosoda (AT) jtec (DOT) or.jp> writes
| Quote: | If you put "extern int foo[3] = {0, 1, 2};" into another file, then
g++ had no problem. If there is a problem of g++, I think the problem
is the interpretation of "extern".
Two problems with that |
1) extern int foo[3] = {0, 1, 2};
is a definition of foo and not just a declaration. In effect the
'extern' is largely ignored.
2) That does not help if you are using sizeof or a template that needs
the complete type. (or I do not think it does)
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Jul 19, 2005 11:30 am Post subject: Re: incomplete type revisited. |
|
|
In article <1121718646.220404.79910 (AT) f14g2000cwb (DOT) googlegroups.com>,
Minkoo Seo <minkoo.seo (AT) gmail (DOT) com> writes
| Quote: | What I am trying to make clear here is the intention of
incomplete type. AFAIK, there are two kinds of incomplete
type that can occur.
1) struct a; // or class a;
2) int array_name[];
The meaning of incomplete type is quite clear when we talk about
the first one, 'struct a', because that's a kind of definition
which lacks the actual definition.
|
No, it is a declaration:-) Until the compilers sees a definition that is
all it is.
| Quote: |
However, incompleteness with regard to the second one,
int array_name[], does not make sense to me. The reason why the
second one is incomplete is that the size of the array is unknown.
|
Exactly, perhaps int array_name[]; is just a declaration, it certainly
seems to behave much like a declaration rather than a definition.
| Quote: |
As I mentioned previously, however, compilers do not need to know the
'size' of an array in C/C++, because keeping size information is
entirely up to programmers.
|
But the compiler does need to know the size in two contexts: providing
an object (i.e. an actual definition) and applying the sizeof operator
which requires a complete type or an expression.
| Quote: |
Why the second type of declaration was sentenced to be incomplete
in the standard?
|
Because that is exactly what it is, the size of an array is part of its
type.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Jul 19, 2005 11:31 am Post subject: Re: incomplete type revisited. |
|
|
In article <200507181449.j6IEnLHH001752 (AT) cliffclavin (DOT) cs.rpi.edu>, Hyman
Rosen <hyrosen (AT) mail (DOT) com> writes
| Quote: | For what it's worth, Comeau compiles
int foo[3];
int main() { extern int foo[]; }
without complaint.
|
You did not go far enough because you did not attempt to use foo, try:
int foo[3];
int main(){
extern int foo[];
sizeof(foo);
}
I seem to remember that the C usage of extern is slightly different to
C++'s and gets tangled up with C's weird 'tentative definitions'.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Vladimir Marko Guest
|
Posted: Tue Jul 19, 2005 11:33 am Post subject: Re: incomplete type revisited. |
|
|
[email]kanze (AT) gabi-soft (DOT) fr[/email] wrote:
| Quote: | Minkoo Seo wrote:
[...]
As you can see, extern int foo[] succeeds in test.c, but
throws an error in test.cpp. Does that mean 'incomplete type
error' is related to C++ only?
My first reaction was that this was a simple compiler bug. A
test with Sun CC also showed that the code compiled and worked
as expected in C++.
|
My first reaction was that this may be related to the stricter
scoping in C++. But if this was the case the declaration in main
would just hide the namespace scope declaration+definition of foo
and the code would still compile without any problems. However,
the error message clearly says something different.
[...]
| Quote: | On the other hand, there is no doubt that:
extern int foo[] ;
// ...
int foo[ 3 ] ;
is legal. The only difference here is in the order in which the
compilers see the declarations.
|
The order doesn't matter. You can have any number of declarations
before and/or after the definition.
[...]
| Quote: | The
error messages you are seeing are for the declaration. The
declaration is for an incomplete type. A previous declaration
was for a complete type.
|
As if you couldn't write
struct A { }; // declaration + definition
struct A; // declaration (for an incomplete type???)
| Quote: | Interestingly enough, in this case, they [authors of g++] also
disagree with the authors of gcc, although the rule is
pretty much the same in the two languages.
|
If you put it this way, they even disagree with themselves:
extern int foo[]; // OK
int foo[]={1,2,3};
extern int foo[]; // OK
void bar(){
extern int foo[]; // g++: ERROR -- SHOULD BE OK
}
I've just submitted a bug report:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22556 ,
extern array: compatible declaration at function scope refused .
Regards,
Vladimir Marko
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Minkoo Seo Guest
|
Posted: Tue Jul 19, 2005 3:57 pm Post subject: Re: incomplete type revisited. |
|
|
| Quote: | 1) struct a; // or class a;
2) int array_name[];
[...]
Why the second type of declaration was sentenced to be incomplete
in the standard?
Because that is exactly what it is, the size of an array is part of its
type.
|
I've got a couple of questions out of my ignorance.
1)
Does it conform to standard to say that 'the type of int array_name[]
is different from int array_name[3]'?
AFAIK, incomplete type like int array_name[] become completed after
a compiler sees the definition int array_name[3]. I also believe
that such a completing process render [] and [3] everything but a
*disparate types*.
2)
As to the original question of the first posting:
int array_name[3];
int main()
{
extern int array_name[];
...
}
Here, I strongly believe that any compiler sees 'int array_name[3]'
before seeing 'extern int array_name[]', because that's the way
how lexers works. So, I think 'array_name' become complete when
compilers sees the 'extern int array_name[]' declaration, making
it a type-compatible declaration(or definition, whatsoever.)
But, opposed to my reasoning, g++ raise an error when above code
is compiled. What's the things that I don't understand here?
Regards,
Minkoo Seo
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Hyman Rosen Guest
|
Posted: Tue Jul 19, 2005 7:12 pm Post subject: Re: incomplete type revisited. |
|
|
Minkoo Seo wrote:
| Quote: | Why the second type of declaration was sentenced to be incomplete
in the standard?
|
Because it is. Saying
typedef struct a x; x y;
doesn't work because x is incomplete, and saying
typedef int x[]; x y;
doesn't work either, for the same reason.
In either case, sizeof(x) is illegal as well.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Wed Jul 20, 2005 9:50 am Post subject: Re: incomplete type revisited. |
|
|
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
| Quote: | In article <49c1da0b.0507181842.36758207 (AT) posting (DOT) google.com>, Tokyo Tomy
[email]hosoda (AT) jtec (DOT) or.jp[/email]> writes
If you put "extern int foo[3] = {0, 1, 2};" into another file, then
g++ had no problem. If there is a problem of g++, I think the problem
is the interpretation of "extern".
Two problems with that
1) extern int foo[3] = {0, 1, 2};
is a definition of foo and not just a declaration. In effect the
'extern' is largely ignored.
2) That does not help if you are using sizeof or a template that needs
the complete type. (or I do not think it does)
|
According to my naive understanding, "extern" requires linker
linkag(incomplete type becomes complete type after the linkage), so it
is natural for sizeof and template not to work, because they need
compile time solution and incomplete type is still incomplete. On
this, I said there would be no problems, if a linker linkage was
carried out in the original code. (Maybe "extern" should be added to
foo[3] = {1, 2, 3})
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Tokyo Tomy Guest
|
Posted: Wed Jul 20, 2005 9:51 am Post subject: Re: incomplete type revisited. |
|
|
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
| Quote: | In article <49c1da0b.0507181842.36758207 (AT) posting (DOT) google.com>, Tokyo Tomy
[email]hosoda (AT) jtec (DOT) or.jp[/email]> writes
If you put "extern int foo[3] = {0, 1, 2};" into another file, then
g++ had no problem. If there is a problem of g++, I think the problem
is the interpretation of "extern".
Two problems with that
1) extern int foo[3] = {0, 1, 2};
is a definition of foo and not just a declaration. In effect the
'extern' is largely ignored.
2) That does not help if you are using sizeof or a template that needs
the complete type. (or I do not think it does)
|
[snip]
Continued from my previous mail
I understand the following currently working g++ code would
brake. It seems that the code is strange and a surprise to me, but if
such codes as below are useful, I should give up my idea.
#include <iostream>
using namespace std;
class C {
int i;
} c;
int main(void)
{
extern class C c;
cout << sizeof(c) << endl;
return EXIT_SUCCESS;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Jul 20, 2005 3:01 pm Post subject: Re: incomplete type revisited. |
|
|
Tokyo Tomy wrote:
| Quote: | Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote in
message news:<XoVaEOPmoN3CFwax (AT) robinton (DOT) demon.co.uk>...
In article
[email]49c1da0b.0507181842.36758207 (AT) posting (DOT) google.com[/email]>, Tokyo
Tomy <hosoda (AT) jtec (DOT) or.jp> writes
If you put "extern int foo[3] = {0, 1, 2};" into another
file, then g++ had no problem. If there is a problem of
g++, I think the problem is the interpretation of "extern".
Two problems with that
1) extern int foo[3] = {0, 1, 2};
is a definition of foo and not just a declaration. In effect
the 'extern' is largely ignored.
|
(Unless the data are const, of course:-).)
| Quote: | 2) That does not help if you are using sizeof or a template
that needs the complete type. (or I do not think it does)
According to my naive understanding, "extern" requires linker
linkag(incomplete type becomes complete type after the
linkage), so it is natural for sizeof and template not to
work, because they need compile time solution and incomplete
type is still incomplete. On this, I said there would be no
problems, if a linker linkage was carried out in the original
code. (Maybe "extern" should be added to foo[3] = {1, 2, 3})
|
Extern is largely irrelevant here. We're discussing types, and
types don't have linkage. extern is a keyword, which may (or
may not) affect the "linkage" of the symbol (or one of the
symbols in the declaration). It never affects the type, nor for
that matter, a symbol which names a type.
That is, I think, part of the problem. When you say "struct C",
you name a type. A single, unique type (at least in the
relevant scope). Whether that type is complete or not is only a
question of what the compiler knows about that type. When you
say "int a[]", you do not name a type. You are dealing with a
derived type, which doesn't have a simple name. And there are
an infinite number of different concrete types which may be used
for the definition. Which causes problems for things like
function overload resolution and template instantiation, where
you need to know the exact type, even if you don't need to know
anything about it.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Jul 20, 2005 3:02 pm Post subject: Re: incomplete type revisited. |
|
|
Vladimir Marko wrote:
| Quote: | kanze (AT) gabi-soft (DOT) fr wrote:
Minkoo Seo wrote:
[...]
As you can see, extern int foo[] succeeds in test.c, but
throws an error in test.cpp. Does that mean 'incomplete type
error' is related to C++ only?
My first reaction was that this was a simple compiler bug.
A test with Sun CC also showed that the code compiled and
worked as expected in C++.
My first reaction was that this may be related to the stricter
scoping in C++. But if this was the case the declaration in
main would just hide the namespace scope
declaration+definition of foo and the code would still compile
without any problems. However, the error message clearly says
something different.
|
Exactly.
| Quote: | [...]
On the other hand, there is no doubt that:
extern int foo[] ;
// ...
int foo[ 3 ] ;
is legal. The only difference here is in the order in which
the compilers see the declarations.
The order doesn't matter. You can have any number of
declarations before and/or after the definition.
|
At least in the standard, there is text describing what happens
if an incomplete declaration is *later* completed. And not the
slightest idea as to what it means for the type to have been
completed before the incomplete declaration.
And this seems to really be the case with g++: if you inverse
the order of the definitions of main and foo in his function,
g++ compiles it.
| Quote: | [...]
The error messages you are seeing are for the declaration.
The declaration is for an incomplete type. A previous
declaration was for a complete type.
As if you couldn't write
struct A { }; // declaration + definition
struct A; // declaration (for an incomplete type???)
|
Interestingly enough:
int foo[3] ;
extern int foo[] ;
causes no problems in g++ either. The problem only occurs if
the extern is in a function (a nested scope). And of course, if
you write "struct A;" in a function, you have declared a new,
function local type, and have not named the previously completed
type defined at namespace scope.
| Quote: | Interestingly enough, in this case, they [authors of g++]
also disagree with the authors of gcc, although the rule is
pretty much the same in the two languages.
If you put it this way, they even disagree with themselves:
extern int foo[]; // OK
int foo[]={1,2,3};
extern int foo[]; // OK
void bar(){
extern int foo[]; // g++: ERROR -- SHOULD BE OK
}
I've just submitted a bug report:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22556 ,
extern array: compatible declaration at function scope refused .
|
I too think that it is a bug in g++. But there are enough other
odd things going on here that it is understandable. I don't
think their behavior makes sense -- it is definitly wrong. But
I'm not really sure on reading the standard what the correct
behavior should be.
(I know what I intuitively want it to be, which is pretty much
what you seem to think it should be. But what I intuitively
want, and what the standard says, are often two different
things.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|