• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: just C++ in xcode
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: just C++ in xcode


  • Subject: Re: just C++ in xcode
  • From: Andreas Grosam <email@hidden>
  • Date: Thu, 29 Sep 2005 15:07:48 +0200


On 29.09.2005, at 05:53, Marshall Clow wrote:

Maybe this is a C++ question not having to do with
xcode, but I'm desparate...

If I have a named namespace in foo1.h:
namespace myspace
{
int myvar;
};

and in foo1.cpp:
#include foo1.h
using namespace myspace;
myvar=1;

and in foo2.cpp
#include foo1.h
using namespace myspace;
cout<<myvar;


If the code in foo1.cpp executes before foo2.cpp, why
should I not find myvar has a value of 1 in foo2?


You've declared two variables.
"extern" is your friend here.
--
-- Marshall

hm...

Although it is pretty off topic, in fact it is a nice example :-)

And i guess, you both missed something!

Firstly, the variable myspace::myvar has external linkage, which means, that there is only one entity with name myspace::myvar - and it can be accessed from foo1.cpp as well as from foo2.cpp.
Secondly, in foo1.cpp the statement

myvar = 1;

isn't an expression statement, but a declaration statement, which introduces a new variable myvar in global namespace with no type (which is illegal in C++). It does not "initialize" the variable myspace::myvar as it might be expected.



In order to fully understand the problem you need to become familiar with the concepts of
1) translation unit
2) scopes
3) namespaces
4) linkage
5) declaration vs definition and ODR (one definition rule)

and a bunch of C++ rules.


To explain this in its whole extent is beyond this scope, though.

Just in brief (and this became pretty long anyway):

1)
In your example you have two translation units: foo1.cpp and foo2.cpp which will be compiled independently. Say, these are TU1 and TU2.

A TU contains a set of declarations.

3)
A namespace N denotes a certain scope. Any entity declared in a namespace-body, are said to be a member of this namespace. A name declared inside a namespace has "namespace-scope". All other entities not declared in any namespace have "global-scope". (note that there are more scopes, like class scope, etc)

(An entity is a value, object, subobject, base class subobject, array element, variable, function, instance of a function, enumerator, type, class member, template, or namespace.)

4)
A name has a "linkage" if it may denote the same entity declared in another scope, otherwise it has "no linkage".

There are two types of linkage:
1. external linkage:
The entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

2. internal linkage:
The entity it denotes can be referred to by names from other scopes in the same translation unit (but not across different TUs).

When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.


Well, entities beeing *objects* having *namespace scope* - like the global variable myvar in the example -
have internal linkage, if
- explicitly declared static or,
- are a constant, declared with const and have neither been declared extern nor previously declared extern,
otherwise they have external linkage.



5)
A declaration just introduces (or redeclares) a name into a TU, but does not "materialize" an entity.
However, there are declarations which also define an entity:
For names denoting an object a declaration is also a definition unless the extern specifier is used:

These are all definitions:
int a; // yes, this too -- because it's C++ and not C!
extern const int b = 0; // explicit initialization
namespace N { int x; } // defines N and N::x

These are all declarations:
extern int a;
extern const int b;
using N::x;

Some additional notes: the prozess of intialization is somewhat more complex.
The expression on the right side of the "=" is called initializer-clause.
If there is no explicit initializer in a definition, a "default-initializer" is applied. If the object of type T is a scalar type, the object is zero-initalized, means, that it gets the value 0 converted to T. This happens before the function main() is entered.
In your example, myspace::myvar will be initialized to 0.



The One Definition Rule:
No translation unit shall contain more than one definition of any variable, function, class type, enumeration type or template.

This is illformed:

namespace n {
int x;
};
int n::x = 1;

The reason is, that there are two definitions for the same name referring to the same entity.


In your example, it follows that the variable myvar in namespace myspace has external linkage. This means in turn, that TU1 and TU2 refer to the same entity - you didn't create two entities!


If you write

namespace n {
int x;
};
using namespace n;
x = 1;

The statement above
x = 1;
actually introduces a new variable in global space which does not have a type. Introducing a variable with no type should be rejected by the compiler.


In your example, note that the variable myspace::myvar is initialized to 0. This happens before the main() function gets executed.


if you write
namespace n {
extern int x;
};

Like without "extern", the variable has external linkage!
However, it is not a definition anymore! It is just a declaration. It does not *define* the entity n::x and thus it must be defined elsewhere, writing
long n::x = 1;

When writing:
using namespace n;
long x = 1;

in order to initialize the variable n::x, this is not appropriate! You instead introduce a new variable x in global space, and there is still no definition for n::x.



The next interesting question is, when using the declaration of n:x with extern above, and link two TUs together, each defining the variable (object) x::n and initializing it with different values. Guess what happens?

For the solution you may cite the C++ standard, 3.2.3 ;-)




Regards

Andreas

Marshall Clow Idio Software <mailto:email@hidden>

It is by caffeine alone I set my mind in motion.
It is by the beans of Java that thoughts acquire speed,
the hands acquire shaking, the shaking becomes a warning.
It is by caffeine alone I set my mind in motion.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: just C++ in xcode
      • From: "Christopher Nagel" <email@hidden>
References: 
 >just C++ in xcode (From: Joe Kurtz <email@hidden>)
 >Re: just C++ in xcode (From: Marshall Clow <email@hidden>)

  • Prev by Date: Help needed with install path and bundling libraries
  • Next by Date: Re: Help needed with install path and bundling libraries
  • Previous by thread: Re: just C++ in xcode
  • Next by thread: Re: just C++ in xcode
  • Index(es):
    • Date
    • Thread