Can anyone explain this portion of the C++0x draft standard? - c++

From ISO Standard Draft: §3.0/9:
n3234 says:
A name used in more than one translation unit can potentially refer to the
same entity in these translationunits depending on the linkage (3.5) of the
name specified in each translation unit.
Can anyone explain this point with an example, please?
What is that statement actually saying? Can any one prove this point in terms of a program?

Sure! What this is saying is that if you have multiple source files (translation units) that both use some name (for example, the name of a variable, class or function), then it's possible that those different files are talking about the same variable, class, or function, assuming that that entity was declared in a way that makes it visible across different files (that is, depending on its linkage).
For example, if I have this file:
A.cpp:
int globalInt;
int main() {
globalInt = 137;
}
And this one here:
B.cpp:
extern int globalInt;
void foo() {
globalInt = 42;
}
Then in both files, the name globalInt refers to the global int variable globalInt defined in A.cpp. That's all that this point is saying.
Note, however, that if I declare globalInt without external linkage, then the two files will be talking about different variables. For example, in this case:
C.cpp:
static int globalInt;
int main() {
globalInt = 137;
}
D.cpp:
static int globalInt;
void foo() {
globalInt = 42;
}
Now the globalInt variable referenced in C.cpp is not the same as the one in D.cpp, even though they have the same name.
Hope this helps!

Ah, standards... let's obfuscate the obvious.
It's saying that, if you use a global variable with the same name in two different source files, they will be the same variable if they are extern or don't specify at all, but if any of them are declared static then those will be completely independent because they're only visible in that source file.
int a; // can be seen in other files; this may be duplicated in multiple source files
static int b; // can only be used in this file
extern int c; // explicitly using a visible variable "c" defined in another file
("Linkage" is the static/extern/default global, or auto which is almost never mentioned since it means "allocated on the stack", which is the default for variables declared inside a function and obviously not meaningful for a declaration outside a function. "Translation unit" is a common way for standards to avoid mentioning "files".)

Related

block scope extern declaration

The C++11 standard give the code snippet below (I deleted unrelated code) and said the name i have external linkage. (clause 3.5.6)
static int i = 0; // #1
void g() {
extern int i; // #3 external linkage
}
Why do they do this? Did I misunderstand something? The two i refer to the same object in vs2012. And when I use i somewhere else, i got an unresolved external error. I have no idea whether vs2012 support this feature or not.
Edit:
I think VS2012 is doing the right thing. The i in #3 only need to refers to an i that has a linkage. If the compiler can't find one, than the i should be defined in other translation unit. So the two i should refer to the same object in the code snippet above.
The quote from the standard:
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
no matching entity is found, the block scope entity receives external
linkage.
But why people need this feature?
#3 is only a declaration; it states that a variable called i exists somewhere in the program, with external linkage, but does not define that variable. The declaration allows you to use that, rather than the static variable from #1, within the scope of g.
You will also need to define it, in the namespace that contains g. In this case, it will have to be in a different translation unit, so that it doesn't conflict with the static variable with the same name.
To be clear, there are two different variables called i here, as explained in the paragraph following the example. #1 is defined here; #3 is only declared, and needs a separate definition.
static int i = 0; // #1
void g() {
extern int i; // #3 external linkage
}
The first static i is a declaration and is visible only in the current source file.
extern int i;
tells the compiler I don't mean this static i but another i defined somewhere else. If you haven't defined it somewhere else (in another translation unit) you will get the undefined reference.
And this doesn't break the ODR because this (the static) i is static (visible only in this unit).
extern int i;
Promises compiler I will give you an int i.
The static int i=0; is not that promised variable, and you have to declare a int i somewhere else visible to that extern variable declaration.
In other words extern int i; and static int i=0; are two irrelevant variables.

How to work with variable in namespace

I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)
test.h:
namespace test{
static int testNum=5;
void setNum(int value);
}
main.cpp:
#include <test.h>
int test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...
I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?
Thank you
First, your misunderstanding has nothing to do with namespaces, it's only about static. For the rest of this answer I'm going to refer to simply testNum because the fact it's in a namespace is irrelevant.
I'm also assuming you have another file, probably called test.cpp, which also includes test.h and defines the setNum function.
When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared static it means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files define static int testNum then each file has its own internal variable with that name, distinct from the testNum in every other file (in fact one file could have static int testnum and another could have static double testnum and another static char* testNum, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its own testNum.
So with static on your variable in a header you have a different variable called testNum in every file that includes test.h. That means if you set testNum in one file and call a function in a different file which uses testNum it refers to a different variable, which just happens to have the same name.
Because of this, declaring non-const static variables in headers is almost always wrong.
Without static you would have a definition of the testNum variable in every file that includes test.h, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declare the variable in the header, but not define it, which you do by telling the compiler the variable is extern:
extern int testNum; // N.B. no "= 1" here
That tells the compiler there is a variable with "external linkage" called testNum, so when code refers to testNum it will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring an extern variable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly one file (i.e. not in a header that gets included in multiple files) you define it:
int testNum = 1;
static at namespace scope is a misnomer, and shouldn't be used. It
means simply that the entity declared static has internal name binding;
in other words, that the same name in other translation units will refer
to a different entity, and in the case of variable definitions, that
there will be a separate instance of the variable in each translation
unit. It has no effect on lifetime. (All variables declared or
defined at namespace scope have static lifetime.)
static at namespace scope is also deprecated. Don't use it.
With regards to declaring a variable in a header: prefix it with
extern, and not static. If a variable is declared extern, and
there is no initialization, the declaration is not a definition. Of
course, in this case, you must provide a definition somewhere (in a
single source file). Something along the lines of:
extern int testNum = 5;
int testNum = 5;
int testNum; // implicitly initialized with 0.
EDIT:
To clarify somewhat: there is some confusion here between lifetime and
name binding:
an object has a lifetime (auto, static or dynamic—or temporary, or exception), and
a name is bound to an entity; if the name is declared to be a variable, the entity is an object.
Do not confuse the keyword static with static lifetime. (Functions
can be static, but functions have no defined lifetime in C++; they're
just there.)
The rules regarding these are not very orthognal. Basically, with
regards to lifetime:
all variables declared at namespace scope have static lifetime, always,
variables declared at local scope have auto lifetime unless they are declared static, and
variables declared at class scope have the lifetime of the class object which contains them, unless they are declared static.
regards to lifetime.
Objects with static lifetime come into being sometime before main, and
live until after you return from main.
With regards to name binding:
variables declared at namespace scope have external name binding,
unless they are declared static, in which case they have internal
name binding (but this use of static is deprecated), or if they are
const, and are not declared extern,
variables declared at class scope have external name binding, even if they are declared static, and
variables declared at block scope have no binding.
Finally, there is the question of whether a declaration is a definition
or not. If it is a definition, memory is allocated and the object is
(or may be) initialized. If it is not a definition, it simply tells the
compiler that there is a definition somewhere else for the entity
(object) declared in the declaration. In general, a variable
declaration is a definition unless it is declared extern and does
not have an initializer.
You might want to make sure your code actually has problems before you post it asking what's wrong ;)
I copy/pasted and fixed your typos, and manually did the include:
#include <iostream>
using namespace std;
namespace test{
static int testNum=5;
void setNum(int value);
}
void test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
result:
$ ./a.out
9
What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as extern.

In C, importance and usage of extern storage class specifier [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is external linkage and internal linkage in C++
Actually I want to know the importance of extern.
First I wrote some code :
file1.h
extern int i;
file2.c
#include<stdio.h>
#include "file1.h"
int i=20;
int main()
{
printf("%d",i);
return 0;
}
Now my question is that: what is the use of extern variable when I have to define the i in file2.c, declaring in file1.h is in which way useful to me .
sudhanshu
extern allows you to declare a variable (notify the compiler of its existence) without defining it (bringing it into existence). The general rule is that you can declare things as many times as you want, but you can only define them once.
This is useful if, for example, it will be defined elsewhere.
Consider:
file1.c: file2.c:
extern int xyzzy; int xyzzy;
void fn (void) {
xyzzy = 42;
}
When you link together those two functions, there will be one xyzzy, the one defined in file2.c, and that's the one that fn will change.
Now that happens even without the extern. What the extern does is to declare that xyzzy exists to file1.c so that you don't get any I don't know what the blazes "xyzzy" is errors.
In your particular case (if those are your only two files), you don't need it. It's only needed if you had another file that #included file1.h and tried to access i.
It's useful when you have three files:
foo.h
extern int i;
void bar();
a.c:
#include "foo.h"
int i = 6;
int main(){
bar();
}
b.c:
#include "foo.h"
void bar(){
printf("%d\n", i);
}
As you can see, i is shared between both a.c and b.c, not redefined per-file, as would happen without the extern keyword.
The "extern" declaration in C is to indicate that there is an existence of, and the type of, a global variable.
In C mostly each .c file behaves like a seperate module. Hence a variable with "extern" is something that is defined externally to the current module.
It is always a better practise to define the global in one place, and then declare extern references to it in all the other places. When refering to globals provided by any shared library, this is important in order to make sure that your code is referring the correct and common instance of the variable.
From Wikipedia:
When a variable is defined, the compiler allocates memory for that
variable and possibly also initializes its contents to some value.
When a variable is declared, the compiler requires that the variable
be defined elsewhere. The declaration informs the compiler that a
variable by that name and type exists, but the compiler need not
allocate memory for it since it is allocated elsewhere.
Extern is a way to explicitly declare a variable, or to force a
declaration without a definition
If a variable is defined in file 1, in order to utilize the same
variable in another file, it must be declared. Regardless of the
number of files, this variable is only defined once, however, it must
be declared in any file outside of the one containing the definition.
If the program is in several source files, and a variable is defined
in file1 and used in file2 and file3, then extern declarations are
needed in file2 and file3 to connect the occurrences of the variable.
Having extern tells the compiler its a declaration of a variable.
In your example in file1.h imagine what would happen if you didn't specify extern keyword. It will look like there are two definitions of int i. Also, a header file can be included in many .c files. If you compile those .c files and link them, linker would see multiple definitions of the same variable.
extern keyword allows you to say to the compiler ... " Use this variable right now .. I will define and initialize it later ".. i.e " Compile it now .. I will link to its definition later".
You can extern the variable when you define it in some other file and you want to use it in the current context..
The declaration in the header allows you to access the variable from more than one source file, while still only defining it in one place.

How to declare a global variable in C++

I know one should not use global variables but I have a need for them. I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp file, that variable could not be found. So it was not really global. Isn't it so that one has to create a header file GlobalVariabels.h and include that file to any other *cpp file that uses it?
I have read that any variable declared outside a function is a global variable. I have done so, but in another *.cpp File that variable could not be found. So it was not realy global.
According to the concept of scope, your variable is global. However, what you've read/understood is overly-simplified.
Possibility 1
Perhaps you forgot to declare the variable in the other translation unit (TU). Here's an example:
a.cpp
int x = 5; // declaration and definition of my global variable
b.cpp
// I want to use `x` here, too.
// But I need b.cpp to know that it exists, first:
extern int x; // declaration (not definition)
void foo() {
cout << x; // OK
}
Typically you'd place extern int x; in a header file that gets included into b.cpp, and also into any other TU that ends up needing to use x.
Possibility 2
Additionally, it's possible that the variable has internal linkage, meaning that it's not exposed across translation units. This will be the case by default if the variable is marked const ([C++11: 3.5/3]):
a.cpp
const int x = 5; // file-`static` by default, because `const`
b.cpp
extern const int x; // says there's a `x` that we can use somewhere...
void foo() {
cout << x; // ... but actually there isn't. So, linker error.
}
You could fix this by applying extern to the definition, too:
a.cpp
extern const int x = 5;
This whole malarky is roughly equivalent to the mess you go through making functions visible/usable across TU boundaries, but with some differences in how you go about it.
You declare the variable as extern in a common header:
//globals.h
extern int x;
And define it in an implementation file.
//globals.cpp
int x = 1337;
You can then include the header everywhere you need access to it.
I suggest you also wrap the variable inside a namespace.
In addition to other answers here, if the value is an integral constant, a public enum in a class or struct will work. A variable - constant or otherwise - at the root of a namespace is another option, or a static public member of a class or struct is a third option.
MyClass::eSomeConst (enum)
MyNamespace::nSomeValue
MyStruct::nSomeValue (static)
Declare extern int x; in file.h.
And define int x; only in one cpp file.cpp.
Not sure if this is correct in any sense but this seems to work for me.
someHeader.h
inline int someVar;
I don't have linking/multiple definition issues and it "just works"... ;- )
It's quite handy for "quick" tests... Try to avoid global vars tho, because every says so... ;- )

No linker error when global variable declared static in the header file [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Static variables in C++
// x.h
int i = 3;
// x1.cpp
#include"x.h"
//...
// x2.cpp
#include"x.h"
//...
Above code will give linker error. However If I declare,
//x.h
static int i = 3;
It doesn't give linker error in gcc, even we have the same #include! Are we creating different static int i; for every .cpp file ? Will it cause any silent linking bug (due to same name)?
When C code is compiled, it's one "translation unit" at a time. Early on, #includes are expanded into the text of the referenced files. So what you've got in the static case is equivalent to x1.cpp saying static int i = 3; and x2.cpp doing the same. And static in this context means roughly "don't share this with other translation units."
So yes, when you use static there you are making two different i variables which have nothing to do with each other. This will not cause a linking error.
int x; is a definition of the entity x. The One Definition Rule of C++ says that any variable that is used shall be defined exactly once in the program. Hence the error.
static says that x has internal linkage. That is, the x's that appear in one.cpp and two.cpp are two different unrelated entities.
The C++ standard says that the use of static in this case is deprecated(As per Steve's comment, in C++0x it's undeprecated). Anonymous namespaces provide a superior alternative.
namespace
{
int x;
}
Also note that unlike C, in C++ const variables of scalar types also have internal linkage. That is
const int x = 7; // won't give you an error if included in different source files.
HTH
Are we creating different static int i; for every .cpp file ?
Yes
Will it cause any silent linking bug (due to same name)?
No. Due to static, they have different names.
If this isn't the behavior you want, you need to use extern in the header file, and allocate the variable in one translation unit (.cpp file)
static creates a global variable that is only visible inside the unit.
If you want to use a variable in more than on ecompilation unit, use extern in the header and declare it in the implmenetation without extern.
You get the linker error in your first code example because i is defined and exported in both compilation units. In the second case i is static, so there is no exported symbol because static variables are only visible in the current compilation unit and aren't exported to the linker. In this case you have two independent variables that are both called i.
As written, the code looks like the same i is being accessed by multiple .cpp files, whereas in reality, each .cpp file will have its own copy. This can lead to misunderstandings and bugs.
If you want there to be just one copy of i, the preferred idiom is to wrap it in an accessor function in x.h:
int& GetI() {
static int i = 3; // this initialization only happens once.
return i;
}
If you do want separate copies of i for each .cpp file, a much clearer expression of this is to simply declare i separately in each .cpp file:
namespace {
int i;
}
Putting it in an anonymous namespace as above keeps it from being accessible from other .cpp files, for safety.