Google Groups Home
Help | Sign in
incomplete type revisited.
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  Messages 1 - 25 of 31 - Collapse all  -  Translate all to Translated (View all originals)   Newer >
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Minkoo Seo  
View profile  
 More options Jul 16 2005, 6:26 am
Newsgroups: comp.lang.c++.moderated
From: "Minkoo Seo" <minkoo....@gmail.com>
Date: 16 Jul 2005 06:26:00 -0400
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("%d\n", 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 <iostream>

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-8)
[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-8)
[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 <iostream>

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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 18 2005, 10:03 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 18 Jul 2005 10:03:02 -0400
Local: Mon, Jul 18 2005 10:03 am
Subject: Re: incomplete type revisited.

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.

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.

     [...]

> 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Hyman Rosen  
View profile  
 More options Jul 19 2005, 5:13 am
Newsgroups: comp.lang.c++.moderated
From: Hyman Rosen <hyro...@mail.com>
Date: 19 Jul 2005 05:13:54 -0400
Local: Tues, Jul 19 2005 5:13 am
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Minkoo Seo  
View profile  
 More options Jul 19 2005, 5:30 am
Newsgroups: comp.lang.c++.moderated
From: "Minkoo Seo" <minkoo....@gmail.com>
Date: 19 Jul 2005 05:30:14 -0400
Local: Tues, Jul 19 2005 5:30 am
Subject: Re: incomplete type revisited.
Please let me clarify the third point.

[...]

[...]

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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tokyo Tomy  
View profile  
 More options Jul 19 2005, 5:35 am
Newsgroups: comp.lang.c++.moderated
From: hos...@jtec.or.jp (Tokyo Tomy)
Date: 19 Jul 2005 05:35:44 -0400
Local: Tues, Jul 19 2005 5:35 am
Subject: Re: incomplete type revisited.

[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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vladimir Marko  
View profile  
 More options Jul 19 2005, 7:33 am
Newsgroups: comp.lang.c++.moderated
From: "Vladimir Marko" <swe...@post.sk>
Date: 19 Jul 2005 07:33:45 -0400
Local: Tues, Jul 19 2005 7:33 am
Subject: Re: incomplete type revisited.

ka...@gabi-soft.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.

[...]

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

[...]

> 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, 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Francis Glassborow  
View profile  
 More options Jul 19 2005, 7:29 am
Newsgroups: comp.lang.c++.moderated
From: Francis Glassborow <fran...@robinton.demon.co.uk>
Date: 19 Jul 2005 07:29:53 -0400
Local: Tues, Jul 19 2005 7:29 am
Subject: Re: incomplete type revisited.
In article <49c1da0b.0507181842.36758...@posting.google.com>, Tokyo Tomy
<hos...@jtec.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.

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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Francis Glassborow  
View profile  
 More options Jul 19 2005, 7:30 am
Newsgroups: comp.lang.c++.moderated
From: Francis Glassborow <fran...@robinton.demon.co.uk>
Date: 19 Jul 2005 07:30:50 -0400
Local: Tues, Jul 19 2005 7:30 am
Subject: Re: incomplete type revisited.
In article <1121718646.220404.79...@f14g2000cwb.googlegroups.com>,
Minkoo Seo <minkoo....@gmail.com> writes

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

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

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

>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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Francis Glassborow  
View profile  
 More options Jul 19 2005, 7:31 am
Newsgroups: comp.lang.c++.moderated
From: Francis Glassborow <fran...@robinton.demon.co.uk>
Date: 19 Jul 2005 07:31:33 -0400
Local: Tues, Jul 19 2005 7:31 am
Subject: Re: incomplete type revisited.
In article <200507181449.j6IEnLHH001...@cliffclavin.cs.rpi.edu>, Hyman
Rosen <hyro...@mail.com> writes

>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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Minkoo Seo  
View profile  
 More options Jul 19 2005, 11:57 am
Newsgroups: comp.lang.c++.moderated
From: "Minkoo Seo" <minkoo....@gmail.com>
Date: 19 Jul 2005 11:57:45 -0400
Local: Tues, Jul 19 2005 11:57 am
Subject: Re: incomplete type revisited.

> >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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Hyman Rosen  
View profile  
 More options Jul 19 2005, 3:12 pm
Newsgroups: comp.lang.c++.moderated
From: Hyman Rosen <hyro...@mail.com>
Date: 19 Jul 2005 15:12:44 -0400
Local: Tues, Jul 19 2005 3:12 pm
Subject: Re: incomplete type revisited.

Minkoo Seo wrote:
> 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tokyo Tomy  
View profile  
 More options Jul 20 2005, 5:50 am
Newsgroups: comp.lang.c++.moderated
From: hos...@jtec.or.jp (Tokyo Tomy)
Date: 20 Jul 2005 05:50:27 -0400
Local: Wed, Jul 20 2005 5:50 am
Subject: Re: incomplete type revisited.

Francis Glassborow <fran...@robinton.demon.co.uk> wrote in message <news:XoVaEOPmoN3CFwax@robinton.demon.co.uk>...
> In article <49c1da0b.0507181842.36758...@posting.google.com>, Tokyo Tomy
> <hos...@jtec.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.

> 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Tokyo Tomy  
View profile  
 More options Jul 20 2005, 5:51 am
Newsgroups: comp.lang.c++.moderated
From: hos...@jtec.or.jp (Tokyo Tomy)
Date: 20 Jul 2005 05:51:53 -0400
Local: Wed, Jul 20 2005 5:51 am
Subject: Re: incomplete type revisited.

Francis Glassborow <fran...@robinton.demon.co.uk> wrote in message <news:XoVaEOPmoN3CFwax@robinton.demon.co.uk>...
> In article <49c1da0b.0507181842.36758...@posting.google.com>, Tokyo Tomy
> <hos...@jtec.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.

> 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++&#12288;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! ]

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 20 2005, 11:02 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 20 Jul 2005 11:02:29 -0400
Local: Wed, Jul 20 2005 11:02 am
Subject: Re: incomplete type revisited.

Exactly.

> [...]
> > 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.

> [...]
> > 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.

> > 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 20 2005, 11:03 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 20 Jul 2005 11:03:16 -0400
Local: Wed, Jul 20 2005 11:03 am
Subject: Re: incomplete type revisited.

Minkoo Seo wrote:
> > >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]'?

The standard says so explicitly.  In the context of your
original code, however, it doesn't say clearly what the
consequences should be.

(Note that in the case of g++, scope makes a difference:

    int foo[ 3 ];
    extern int foo[] ;

is perfectly legal, but putting the second declaration in a
function makes it illegal.  Which makes me suspect that making
it illegal is an accidental bug in g++, and not intentional.)

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

Once the type is completed, it is completed.  Yes.  But the
standard makes it clear as well that between the incomplete
declaration and the moment it becomes completed, the types are
different.  (Not that many compilers follow the standard on this
one.)

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

There is (officially, at least) no concept of type compatibility
in the C++ standard.  Two things are the same type, or they are
not.  Except that an incomplete type is not the same type as a
complete type (in this case), and something that was declared
with an incomplete type can have the type completed *later*.
(The standard regretfully doesn't say anything as to what the
type should be if the type was already complete at the point of
the declaration with the incomplete type.)

> But, opposed to my reasoning, g++ raise an error when above
> code is compiled.  What's the things that I don't understand
> here?

I'm tempted to ask: what do you want to understand?  The
compiler writers don't seem to understand it, so why should
you:-)?

Seriously: put your extern's and incomplete types at namespace
scope in a header file.  Make sure that the header is included
before any definition, and you shouldn't have any problems.  As
for understanding... since it's not at all clear what the
standard really says, the only solution is to join the committee
and help define 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 20 2005, 11:01 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 20 Jul 2005 11:01:50 -0400
Local: Wed, Jul 20 2005 11:01 am
Subject: Re: incomplete type revisited.

Tokyo Tomy wrote:
> Francis Glassborow <fran...@robinton.demon.co.uk> wrote in
> message <news:XoVaEOPmoN3CFwax@robinton.demon.co.uk>...
> > In article
> > <49c1da0b.0507181842.36758...@posting.google.com>, Tokyo
> > Tomy <hos...@jtec.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:-).)

> > 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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 20 2005, 11:04 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 20 Jul 2005 11:04:49 -0400
Local: Wed, Jul 20 2005 11:04 am
Subject: Re: incomplete type revisited.

Minkoo Seo wrote:
> Please let me clarify the third point.
> [...]
> 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[];

There's a third.  Void is an incomplete type.

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

Because there are some things you cannot do with it.  I think
the critical aspect is that you cannot create an object with an
incomplete type.  You might be able have a pointer to the
object, or a reference to the object, or a declaration refering
to the object, but you cannot have a definition.  When you have
an incomplete type, some aspect of the type is undefined, and
the type must be completed before an object of that type can be
defined.  (The incomplete type void cannot be completed, and so
we can never define an object with type void.)

Beyond that, of course, you are right in that the three types of
incomplete types are incomplete in different ways, which results
in different constraints.  In this case, the most important
difference (and the one which is causing the problems), is that
the incomplete type 'struct a' is a placeholder for exactly one
type.  We may not have all of the information concerning that
type, but we do know how to 'name' it (e.g. as in name
mangling).  In the case of 'int a[]', the "incomplete type" is
in fact a placeholder for a set of types, and a priori, we don't
know how to name it.  Except that in certain uses, we have to be
able to name it:

    template< typename T > vod f( T& a ) ;
    extern int a[] ;

    f( a ) ;        //  legal, but how to instantiate f?

I presume that this is the motivation for saying that the
incomplete type in this case is a distinct type.

Given your initial code:

    int foo[ 3 ] = { 0, 1, 2 } ;

    int
    main()
    {
        extern int foo[] ;
        cout << typeid( foo ).name() << std::endl ;
        return 0 ;
    }

I see three possible interpretations: it's an error, the type of
foo in the typeid is an array[unknown] of int, and the type
of foo in the typeid is an array[3] of int.  Intuitively, I
would expect that latter -- of the three compilers I have at
hand (Sun CC, g++ and VC++), g++ treats it as an error, and the
other two accept it, and treat it as array[unknown] of int.

If I modify the code to be C (using sizeof, instead of typeid),
I get an error from gcc, a warning from Sun cc, and the
generated code outputs 0, and VC++ accepts it fine, and outputs
12.  Intuitively, I would go with the behavior of VC++ for C,
but the standard does seem a bit vague as to what is to be
expected.

> 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?

Because it's not complete:-).

The problem, in my mind, is more why it doesn't behave like the
other incomplete types; I suspect that it has to do with the
fact than an incomplete class has a name, which gives the type
itself scope.  And any attempt to declare the type in a
different scope actually declares a new type -- there's no way
to apply the extern modifier to the name of a class.

Having said that, I think you're right in that we have three
distinct things (arrays of unspecified dimension, class forward
declarations, and void), and calling them all the same thing (an
incomplete type) only leads to confusion.

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 20 2005, 11:03 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 20 Jul 2005 11:03:39 -0400
Local: Wed, Jul 20 2005 11:03 am
Subject: Re: incomplete type revisited.

Francis Glassborow wrote:
> In article
> <1121718646.220404.79...@f14g2000cwb.googlegroups.com>, Minkoo
> Seo <minkoo....@gmail.com> writes
> >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.

I think he's using the word "definition" somewhat informally,
and not in the strict sense it is used in the standard.  I think
that his point is that there is a difference between the two
declarations: the first tells us (and the compiler) almost
nothing about the actual type -- we know that it will be a class
type, and that's about it.  The second actually tells us (and
the compiler) quite a bit: we know not only that it will be an
array type, but also an array of what.

There are obviously reasons for this, linked at least partially
to the strange beast that arrays are in C++.  The consequence,
however, is that the two cases need to be handled differently in
many contexts.  Consider, for example, the following:

    #include <iostream>
    #include <ostream>

    template< typename T >
    void f( T const* )
    {
        static int i = 0 ;
        std::cout << ++ i ;
    }

    //      incomplete types.
    struct S ;
    extern int a[] ;

    void
    f1()
    {
        f( (S*)0 ) ;
        f( a ) ;
    }

    //      complete the types.
    struct S
    {
        int s1 ;
        int s2 ;
    } ;
    int a[ 3 ] ;

    void
    f2()
    {
        f( (S*)0 ) ;
        f( a ) ;
    }

    int
    main()
    {
        f1() ;
        f2() ;
        return 0 ;
        std::cout << std::endl ;
        return 0 ;
    }

According to the standard, this code should output 1121 -- in
f1, a has the incomplete type int[], and in f2, it has the
complete type int[3].  At least, that is the only reasonable
interpretation I can give to §3.9/7: "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 are different types."
But I may have missed something; both Sun CC and g++ output 1122
(presumably using the same template instantiation for the
incomplete array in f1 and the complete type in f2).

About all I really feel confident in saying at this point is: 1)
the issue is relatively complex, and 2) the standard is far from
clear about it.  (And in consequence of 2, 3) compilers differ
considerably concerning these points.)

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

Who cares.  You can't have a definition without having a
complete type.  But a declaration doesn't necessarily imply an
incomplete type.  The issue here is incomplete type vs. complete
type.

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

Again, that doesn't invalidate his point.  There are things you
can do, and things you can't, and they aren't the same depending
on the source of the incompletion.  Consider:

    struct S ;
    extern int a1[] ;
    extern S   a2[ 5 ] ;

Both arrays have incomplete types.  You can, however, index into
the first, but not into the second.

You and I both know that this is because an array converts into
a pointer to the first element, resulting in an int* -- a
complete type -- in one case, and an S* in the other, and that
pointer arithmetic is not allowed on an incomplete type.  And
that indexation is defined in terms of pointer arithmetic.  But
surely you can see that the issue can be confusing to a
beginner.

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

Or the absence of the size.  I find it pretty confusing, myself,
that some incomplete types are independant types, whereas others
aren't.  Apparently, I'm not alone, since Sun CC, g++, gcc and
VC++ all do different things in some circomstances.

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vladimir Marko  
View profile  
 More options Jul 21 2005, 6:54 am
Newsgroups: comp.lang.c++.moderated
From: "Vladimir Marko" <swe...@post.sk>
Date: 21 Jul 2005 06:54:19 -0400
Local: Thurs, Jul 21 2005 6:54 am
Subject: Re: incomplete type revisited.

You got this one wrong. The only way to match the template
parameters is by using the implicit conversions
   int[] -> int const* and int[3] -> int const*
and the deduced parameters types are S, int, S, int. To get what
you really want you must replace f(a) by f(&a) in f1 and f2 and
the output _will_ be 1121 (at least with gcc 3.3.1-4.0.0 cygwin,
gcc 3.4.2 mingw and MSVC++Toolkit2003).

Vladimir Marko

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vladimir Marko  
View profile  
 More options Jul 21 2005, 6:52 am
Newsgroups: comp.lang.c++.moderated
From: "Vladimir Marko" <swe...@post.sk>
Date: 21 Jul 2005 06:52:49 -0400
Local: Thurs, Jul 21 2005 6:52 am
Subject: Re: incomplete type revisited.

Exactly. And reading the standard I found

3.5/6:

     The name of a function declared in block scope, and the name
     of an object declared by a block scope extern declaration,
     have linkage. If there is a visible declaration of an entity
     with linkage having the same name and type, ignoring entities
     declared outside the innermost enclosing namespace scope, the
     block scope declaration declares that same entity and receives
     the linkage of the previous declaration. If there is more than
     one such matching entity, the program is ill-formed. Otherwise,
     if no matching entity is found, the block scope entity receives
     external linkage.

So, let's have a look on this snippet:

int foo[]={1,2,3};  // (1)

void bar(){
   extern int foo[];  // (2)
   foo[2];  // (3)
   sizeof(foo); // (4)

}

We want
   (1) to declare+define foo as int[3] (with external linkage)
   (2) to redeclare foo from the enclosing namespace
   (3) to be well-formed and bind to foo defined in (1) at compile
       time
   (4) to be well-formed (foo is a complete type)
But the standard could also be interpreted so that
   (1) declares+defines foo as int[3] (with external linkage)
   (2) declares foo at block scope to bind to int foo[] with
       external linkage in the enclosing namespace (the last
       sentence of 3.5/6 applies)
   (3) is well-formed, because of the conversion int[] -> int*
       (see 8.3.4/6);  at link time this will bind to the foo
       defined in (1)
   (4) ill-formed, because the foo visible at block scope is
       incomplete
And if this is correct I guess there is a difference between
the intent and the wording, the wording being normative.

g++ is wrong to refuse (2) anyway, but the PR's subject may
be wrong.

Regards,
Vladimir Marko

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Francis Glassborow  
View profile  
 More options Jul 21 2005, 8:38 am
Newsgroups: comp.lang.c++.moderated
From: Francis Glassborow <fran...@robinton.demon.co.uk>
Date: 21 Jul 2005 08:38:45 -0400
Local: Thurs, Jul 21 2005 8:38 am
Subject: Re: incomplete type revisited.
In article <1121935137.190486.127...@z14g2000cwz.googlegroups.com>,
Vladimir Marko <swe...@post.sk> writes
>g++ is wrong to refuse (2) anyway, but the PR's subject may
>be wrong.

Probably, but I think the programmer is wrong to write it. Consider:

#include <iostream>
#include <istream>
int a[] = {4,5,6};

int main(){
        int a[] = {1,2,3,4};
        {
                extern int a[];
                std::cout << a[2];
        }
        std::cout << a[2];

}

To which a should the extern declaration bind? Actually, whatever the
Standard says, a programmer who relies on it is walking on very thin
ice. There are areas which maybe great fun to test and in doing so we
can develop our understanding but we should keep it at that and not seek
to use such stressful code in any real program.

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Vladimir Marko  
View profile  
 More options Jul 21 2005, 11:52 am
Newsgroups: comp.lang.c++.moderated
From: "Vladimir Marko" <swe...@post.sk>
Date: 21 Jul 2005 11:52:34 -0400
Local: Thurs, Jul 21 2005 11:52 am
Subject: Re: incomplete type revisited.

Francis Glassborow wrote:
> In article <1121935137.190486.127...@z14g2000cwz.googlegroups.com>,
> Vladimir Marko <swe...@post.sk> writes
> >g++ is wrong to refuse (2) anyway, but the PR's subject may
> >be wrong.
> Probably, but I think the programmer is wrong to write it. Consider:

> #include <iostream>
> #include <istream>
> int a[] = {4,5,6};

This a is not visible

> int main(){
>         int a[] = {1,2,3,4};

and this a has no linkage,

>         {
>                 extern int a[];

thus this a refers to "some a" in the innermost enclosing namespace
(see 3.5/6) which happens to be ::a defined in the 3rd line.

>                 std::cout << a[2];

output 6

>         }
>         std::cout << a[2];

output 3

> }
> To which a should the extern declaration bind? Actually, whatever the
> Standard says, a programmer who relies on it is walking on very thin
> ice. There are areas which maybe great fun to test and in doing so we
> can develop our understanding but we should keep it at that and not seek
> to use such stressful code in any real program.

True. Especialy for your example. The simple case we were talking about
is something along the lines of a function declaration in another
function's body. Though I would advise not to use such techniques,
someone may find legitimate reasons to do so.

Vladimir Marko

      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 21 2005, 11:56 am
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 21 Jul 2005 11:56:20 -0400
Local: Thurs, Jul 21 2005 11:56 am
Subject: Re: incomplete type revisited.

You're right, of course.  I changed my idea in mid course, and
got it messed up.  To avoid the array to pointer conversion, you
need to either use references, or an extra level of
indirection.  My original idea was to use the extra level of
indirection, but it didn't work out when I tried to generate the
calls, so I switched to counting on references.  Except that I
forgot to go back and change the template.

At least, I'm happy that at least one compiler agrees with my
reading of the standard:-).

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 21 2005, 6:13 pm
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 21 Jul 2005 18:13:54 -0400
Local: Thurs, Jul 21 2005 6:13 pm
Subject: Re: incomplete type revisited.

But this just concerns linkage.  I don't think that that's a
problem here -- everything has external linkage.

> So, let's have a look on this snippet:
> int foo[]={1,2,3};  // (1)
> void bar(){
>    extern int foo[];  // (2)
>    foo[2];  // (3)
>    sizeof(foo); // (4)
> }
> We want
>    (1) to declare+define foo as int[3] (with external linkage)
>    (2) to redeclare foo from the enclosing namespace
>    (3) to be well-formed and bind to foo defined in (1) at compile
>        time
>    (4) to be well-formed (foo is a complete type)

The first three are obvious, I think, and I doubt that any
compiler gets them wrong.  The real questions are: 1) whether
foo is a complete type, and 2) if it isn't, is the declaration
at (2) an error, or not?

> But the standard could also be interpreted so that
>    (1) declares+defines foo as int[3] (with external linkage)
>    (2) declares foo at block scope to bind to int foo[] with
>        external linkage in the enclosing namespace (the last
>        sentence of 3.5/6 applies)

Up until here, there's no doubt as to what is required.  All of
the compilers conform, too.

>    (3) is well-formed, because of the conversion int[] -> int*
>        (see 8.3.4/6);  at link time this will bind to the foo
>        defined in (1)

Woah.  What does the conversion int[] -> int* have to do with
anything.  This conversion *only* applies in expressions (and
not always there).  For the moment, there aren't any expressions
involving foo.

>    (4) ill-formed, because the foo visible at block scope is
>        incomplete
> And if this is correct I guess there is a difference between
> the intent and the wording, the wording being normative.

First, I don't really know what the intent was.  I think that
there was no intent to be incompatible with C here.  However,
the C standard isn't very clear either, and different C
compilers interpret it differently as well.

> g++ is wrong to refuse (2) anyway, but the PR's subject may be
> wrong.

I don't think that the original poster is a native English
speaker, and I think that he has some trouble expressing himself
in English.  (I wonder, in fact, if the differences aren't just
linguistic, but cultural.  And that when he very humbly lists a
certain number of questions, a native American wouldn't say
something more on the lines "The standard is sure screwed up
here.")  I think, however, that he has hit upon a very real
problem in the standard (and probably a bug in g++ as well).

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
ka...@gabi-soft.fr  
View profile  
 More options Jul 21 2005, 6:19 pm
Newsgroups: comp.lang.c++.moderated
From: ka...@gabi-soft.fr
Date: 21 Jul 2005 18:19:13 -0400
Local: Thurs, Jul 21 2005 6:19 pm
Subject: Re: incomplete type revisited.

The extern declaration can only bind to something which has
external linkage.  There's no question about that.  The
definition of a in main is a red herring.  The extern
declaration of a also hides all declarations in outer scope; I
believe that this is the reasoning behind the behavior of the
EDG front end when it rejects a sizeof on a.

> Actually, whatever the Standard says, a programmer who relies
> on it is walking on very thin ice.

Relies on what?  I think most people would agree that block
scope is not the best place for extern declarations.  The
orginal poster didn't claim that the code was "good", either.
He asked (or at least to me, it seemed like he was asking) a
question about the standard.

> There are areas which maybe great fun to test and in doing so
> we can develop our understanding but we should keep it at that
> and not seek to use such stressful code in any real program.

It's not so much a question of "stress" but conventions.  extern
declarations belong at namespace scope, in headers.  And no
where else.  That's the usual coding convention.  But from a
standards point of view, I think that there is a valid question.

--
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! ]


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Messages 1 - 25 of 31   Newer >
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google