Topic: Question about Program and Linkage (3.5) again


Author: jg <jgu222@gmail.com>
Date: Mon, 7 May 2007 21:15:07 CST
Raw View
===================================== MODERATOR'S COMMENT:
 Apologies for the delay in moderation; this appears to be caused
by my ISP (Cox) dropping and/or blocking e-mail.


===================================== END OF MODERATOR'S COMMENT
C++ std 3.5p6 has the following example:
-------------------------
static void f();
static int i = 0; //1
void g() {
  extern void f(); // internal linkage
  int i; //2: 'i' has no linkage
  {
    extern void f(); // internal linkage
    extern int i; //3: external linkage
  }
}

There are three objects named i in this program. The object with
internal linkage introduced by the declaration in global scope (line //
1), the object with automatic storage duration and no linkage
introduced by the declaration on line //2, and the object with static
storage duration and external linkage introduced by the declaration on
line //3.
----------------------------------

I tried g++ (4.1.1) and i at //3 is the same as i at //1, which is
wrong according
to the standard.  Why does C++ require i at //3 to be an external
object (what is
the rationale ) ?  To me, because this translation unit declares i as
internal linkage
at //1 to hide 'extern i',  Making i at //3 to refer i at //1 is
reasonable.  If this translation
unit wants to use extern i,  it shouldn't have hidden i in the first
place, right ?

For interesting people, here is my example code:
t1.c
----
int y=10;

t.c
---
#include <stdio.h>

static int y = 2;
int main()
{
  printf("y (static y) =%d\n", y);
  {
    int y=-1;
    printf("y (local) =%d\n", y);
    {
      extern int y;
      printf("y (extern) =%d\n", y);
    }
  }
}

%g++ t.c t1.c
%a.out
y (static y) =2
y (local) =-1
y (extern) =2

(y (extern) =2" isn't 10 !

JG

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: James Kanze <james.kanze@gmail.com>
Date: Wed, 9 May 2007 13:11:45 CST
Raw View
On May 8, 5:15 am, jg <jgu...@gmail.com> wrote:
> C++ std 3.5p6 has the following example:
> -------------------------
> static void f();
> static int i = 0; //1
> void g() {
>   extern void f(); // internal linkage
>   int i; //2: 'i' has no linkage
>   {
>     extern void f(); // internal linkage
>     extern int i; //3: external linkage
>   }
>
> }

> There are three objects named i in this program. The object with
> internal linkage introduced by the declaration in global scope (line //
> 1), the object with automatic storage duration and no linkage
> introduced by the declaration on line //2, and the object with static
> storage duration and external linkage introduced by the declaration on
> line //3.
> ----------------------------------

> I tried g++ (4.1.1) and i at //3 is the same as i at //1,
> which is wrong according to the standard.  Why does C++
> require i at //3 to be an external object (what is the
> rationale)?

Because it has to define something:-).  Seriously, I don't think
that the authors of the standard wanted people to write this
sort of thing, so they probably didn't worry too much about
making it intuitive.  All they did was provide an arbitrary
definition so that compiler writers had something to go on.

In this case, in //3, the only "i" which is visible is the one
in //2.  Since it makes no sense to apply "extern" to a local
variable, the decision is that //3 declares (not defines) a new
variable.  Since the "i" in //1 is not visible at this instant,
it can't be that "i".

> To me, because this translation unit declares i as internal
> linkage at //1 to hide 'extern i',

Whether a name is hidden or not depends on scope, not linkage.

> Making i at //3 to refer i at //1 is reasonable.  If this
> translation unit wants to use extern i,  it shouldn't have
> hidden i in the first place, right ?

That would also be reasonable.

As I said, I think the committee just chose one reasonable
possibility, arbitrarily.  In practice, if you want to use a
global "i" defined in another translation unit, anywhere in your
translation unit, you will provide a single extern declaration,
at namespace scope---in fact, this declaration should normally
be in a header file which you include.  And you won't hide this
declaration anywhere.  That's what "best practices" would
certainly recommend, and that's something about which the
committee will seriously consider all of the alternatives, in
order to be relatively sure of choosing the best.  For things
like the above, which are really mostly present for legacy
reasons, and that one doesn't expect to find it well written
code, the committee typically invests a lot less effort in
deciding what is "best".

Finally, since users don't (hopefully) write such code, compiler
writers don't worry about it too much either, as long as they
don't get a bug report, and probably don't consider an error too
important, even if they do get a bug report.  If it would be
trivial to fix the error, fine, but if it required a major
reorganization of the internal structures, most users would
probably prefer the time and effort be invested in other things.

--
James Kanze (GABI Software)             email:james.kanze@gmail.com
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


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: jg <jgu222@gmail.com>
Date: Wed, 9 May 2007 22:56:24 CST
Raw View
===================================== MODERATOR'S COMMENT:

(Apologies for this comment, which is present to bypass broken
spam filtering implemented by Cox.)


===================================== END OF MODERATOR'S COMMENT
On May 9, 12:11 pm, James Kanze <james.ka...@gmail.com> wrote:

Thanks for your posting. I like that.
>
> In this case, in //3, the only "i" which is visible is the one
> in //2.  Since it makes no sense to apply "extern" to a local
> variable, the decision is that //3 declares (not defines) a new
> variable.  Since the "i" in //1 is not visible at this instant,
> it can't be that "i".
>

The "i" in //i is not visible, so is the "that extern i". Making
"extern int i" at
//3 refers to "i" at //1 or "that extern i" is a matter of choice, it
should not
be based on visibility.

JG


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Sun, 13 May 2007 14:53:07 GMT
Raw View


On 5/7/07 8:15 PM, in article
1178551645.212317.208290@p77g2000hsh.googlegroups.com, "jg"
<jgu222@gmail.com> wrote:
> C++ std 3.5p6 has the following example:
> -------------------------
> static void f();
> static int i = 0; //1
> void g() {
>   extern void f(); // internal linkage
>   int i; //2: 'i' has no linkage
>   {
>     extern void f(); // internal linkage
>     extern int i; //3: external linkage
>   }
> }
>
> There are three objects named i in this program. The object with
> internal linkage introduced by the declaration in global scope (line //
> 1), the object with automatic storage duration and no linkage
> introduced by the declaration on line //2, and the object with static
> storage duration and external linkage introduced by the declaration on
> line //3.
> ----------------------------------
>
> I tried g++ (4.1.1) and i at //3 is the same as i at //1, which is
> wrong according
> to the standard.  Why does C++ require i at //3 to be an external
> object (what is
> the rationale ) ?  To me, because this translation unit declares i as
> internal linkage
> at //1 to hide 'extern i',  Making i at //3 to refer i at //1 is
> reasonable.  If this translation
> unit wants to use extern i,  it shouldn't have hidden i in the first
> place, right ?

If i in this example were a function, then //1 and //3 would be referring to
the same function named "i"; but since i is actually the name of a variable
- the rules are reversed and //1 and //3 must refer to different variables
named "i". (So anyone who thinks that the C++ Standard lacks a sense of
humor - is just not looking hard enough to find it).

Thankfully, this state of affairs will not be carried forward into C++09. In
the next Standard, this example code will be ill-formed:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2263.html#426

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: greghe@pacbell.net (Greg Herlihy)
Date: Mon, 14 May 2007 16:43:01 GMT
Raw View


On 5/7/07 8:15 PM, in article
1178551645.212317.208290@p77g2000hsh.googlegroups.com, "jg"
<jgu222@gmail.com> wrote:
> C++ std 3.5p6 has the following example:
> -------------------------
> static void f();
> static int i = 0; //1
> void g() {
>   extern void f(); // internal linkage
>   int i; //2: 'i' has no linkage
>   {
>     extern void f(); // internal linkage
>     extern int i; //3: external linkage
>   }
> }
>
> There are three objects named i in this program. The object with
> internal linkage introduced by the declaration in global scope (line //
> 1), the object with automatic storage duration and no linkage
> introduced by the declaration on line //2, and the object with static
> storage duration and external linkage introduced by the declaration on
> line //3.
> ----------------------------------
>
> I tried g++ (4.1.1) and i at //3 is the same as i at //1, which is
> wrong according
> to the standard.  Why does C++ require i at //3 to be an external
> object (what is
> the rationale ) ?  To me, because this translation unit declares i as
> internal linkage
> at //1 to hide 'extern i',  Making i at //3 to refer i at //1 is
> reasonable.  If this translation
> unit wants to use extern i,  it shouldn't have hidden i in the first
> place, right ?

If i in this example were a function, then //1 and //3 would be referring to
the same function named "i"; but since i is actually the name of a variable
- the rules are reversed and //1 and //3 must refer to different variables
named "i". (So anyone who thinks that the C++ Standard lacks a sense of
humor - is just not looking hard enough to find it).

Thankfully, this state of affairs will not be carried forward into C++09. In
the next Standard, this example code will be ill-formed:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2263.html#426

Greg

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]