In principle, a variable defined outside any function (that is, global, namespace, and class static variables) is initialized before main() is invoked. Such nonlocal variables in a translation unit are initialized in their declaration order
Above are the lines from the class notes given by my lecturer.
#include <iostream>
using namespace std;
int a=99;
int main(int argc, char *argv[])
{
cout<<a<<endl;
cout<<b<<endl;
return 0;
}
int b=100;
There is an error while I run this. Isn't it true that b assigned to 100 before main() is called?
The problem here is not initialisation order: b is indeed initialised before main starts running.
The problem is the "visibility" of b. At the point where main is being compiled, there is no b.
You can fix it by either moving the definition/initialisation of b to before main:
#include <iostream>
using namespace std;
int a = 99;
int b = 100;
int main (int argc, char *argv[]) {
cout << a << '\n';
cout << b << '\n';
return 0;
}
or simply indicate that b exists:
#include <iostream>
using namespace std;
int a = 99;
extern int b;
int main (int argc, char *argv[]) {
cout << a << '\n';
cout << b << '\n';
return 0;
}
int b = 100;
Neither of those two solutions change when b is created or initialised at run-time, they simply make b available within main.
Your lecturer is wrong; global variables are initialised in order of definition, not declaration.
For example,
#include <iostream>
struct S { S(const char *s) { std::cout << s << '\n'; } };
extern S a; // declaration
extern S b; // declaration
int main() { }
S b("b"); // definition
S a("a"); // definition
will print
b
a
The code you posted doesn't work because b is not even declared at the point of use. A declaration (for example, extern int b), is required because C++ (like C) was originally designed as a one-pass compiler.
The problem is here: cout<<b<<endl;
You can't access the variable before it's declaration.
Read carefully.
A variable defined outside any function (B) is initialized before main is invoked (not compiled).
To be compiled correctly B should be defined(and declared) before it's first use (and that's your error: B is used before been declared anywhere).
The problem is the statement b=100;: you can't place a statement in a global scope (except for variable initialization).
If this line remains as is, the code won't compile regardless of b declarations/definitions or the use of b within main or anywhere.
Without this line, the code is correct and works, with b value equals 0, since uninitialized global variables are initialized to 0 (or the line b=100; could be moved into any function scope).
Related
#include <iostream>
using namespace std;
int x=15;
int main()
{
int x=10;
{
int x = 5;
cout<<::x; // should print 10;
}
return 0;
}
Is there any way to print x=10 without changing variable names, variable values and position of cout?
I assume this is an academic question (puzzle) because nobody should write code like that. In the same spirit, here's a way to make it print 10 instead of 15 without changing variable names, variable values and the position of cout:
#include <iostream>
using namespace std;
int x=15;
int main()
{
int x=10;
{
int x = 5;
#define x x-5
cout<<::x; // should print 10;
}
return 0;
}
Normally you should parenthesize such expressions in macros, like (x-5). In this case, that would be counterproductive :)
No you can't
An inner block, because it is a different block, can re-utilize a name existing in an outer scope to refer to a different entity; in this case, the name will refer to a different entity only within the inner block, hiding the entity it names outside.
Further information here: http://www.cplusplus.com/doc/tutorial/namespaces/
You cannot access x=10 in the inner block where you defined x=5. It can only see x=5 as x=10 is hidden at that point.
Ref: 3.3.7/1
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).
If you don't mind some horrible undefined behaviour, we could make assumptions about where local variables are stored on the stack. This works on my machine™ using g++ without any additional flags (although even -O1 breaks it):
#include <iostream>
using namespace std;
int x=15;
int main()
{
int x=10;
{
int x = 5;
cout<<*((&x) + 1); // should print 10;
}
return 0;
}
This is based on the assumption that local variables are placed on the call stack (or some other place) consecutively in main memory, in reverse order of declaration. It breaks in many cases, such as having a different order, having x=10 be placed in a register, or x=10 being optimized away entirely because it's unused.
#include <iostream>
using namespace std;
int x = 15;
int main()
{
int x = 10;
{
int x = 5;
}
cout << x; // should print 10;
return 0;
}
you should probably put cout<< to outside
#include <iostream>
using namespace std;
int main()
{
struct calcvaribles;
{
int a;
int b;
int sum;
};
struct introstructions;
{
char ab[35];
string ac;
};
introstructions outline;
outline.ab = "welcome to my calculator program!";
outline.ac = "please enter any [One] number in the
terminal";
return 0;
}
Error message:
aggregate main()::introstructions outline had incomplete type and cannot be defined
Introstructions outline.
Why are you declaring structs inside main? Just move them into
global scope.
You cannot assign a string literal to a char array as you do here: outline.ab = "welcome to my calculator program!";. Instead, use a const char* or, better yet, as you showed below the char array declaration, std::string, but don't forget to #include <string>.
The problem in your code is that you include a ; after the struct name:
struct calcvaribles;
struct introstructions;
The following should work:
#include <iostream>
#include <string>
using namespace std;
int main() {
struct calcvaribles {
int a;
int b;
int sum;
};
struct introstructions {
string ab;
string ac;
};
introstructions outline;
outline.ab = "welcome to my calculator program!";
outline.ac = "please enter any [One] number in the terminal";
return 0;
}
In this situation the C++ language does not help you since the compiler interprets the code in a completely different way than you expect it.
#include <iostream>
using namespace std;
int main()
{
struct calcvaribles;
Because of the semicolon at the end of the above line, the compiler reads this as:
There is a struct called calcvaribles. It's not clear at this point which fields the struct has, that's to be defined elsewhere. In any case, the struct's name is already known, and if you declare a variable of type pointer to that struct, that's allowed from no on.
{
This opening brace means:
A new scope starts here. Any variable that is declared in this scope will only be available until the corresponding }.
int a;
int b;
int sum;
Instead of being struct fields (what you intended), these are declarations of normal variables. These variables don't do anything, they have no values assigned and their values are not read at all. In summary, these three lines are a big "do nothing" block.
};
The scope ends here. From no on, the variables a, b and sum are no more.
The semicolon is useless as well. It's an empty statement. Allowed but useless.
struct introstructions;
{
char ab[35];
string ac;
};
introstructions outline;
outline.ab = "welcome to my calculator program!";
outline.ac = "please enter any [One] number in the
terminal";
return 0;
}
The same happens with the introstructions type.
Had you written the struct definitions outside of the main function, the compiler would have given you a "syntax error" message. Maybe you did that first, and to fix the error message, you moved everything into the main function.
It's unfortunate that only because of these trailing semicolons, the code you wrote still compiled but means something entirely different. But there's no workaround for that.
#include<stdio.h>
int main(){
int a=10;
{ printf("%d",a);
int a=20;
printf("%d",a);
}
printf(" %d",a);
return 0;
}
Output:10 20 10
In the above code I understand that the visibility of variable a(inside inner block) has scope only within that block therefore I get that particular output.
But the variable a which is declared outside that block should have its scope even within the inner block...Therefore how is it possible for me to again type int a=20;
Shouldn't it give me an error like "redefinition of a" and "previous declaration of a was here". Like if I use
int b=10;
int b=15;
My second problem is this
void main() {
static int a=10;
{
printf("%d ",a);
static int a=20;
printf("%d",a);
}
printf(" %d",a);
}
Apart from the same doubt as the previous code about why I'm not getting an error like "redefinition of a", This is my doubt related to this code.
For the above code i get the same Output: 10 20 10 but what I was expecting was
10 20 20
I mean in the inner block once static int a is reinitialized to 20 shouldn't it be the same value even after it exits the block? because the a static variable's scope is throughout the entire program.
Answer for the first problem: It is called variable shadowing. From Wikipedia:
variable shadowing occurs when a variable declared within a certain
scope (decision block, method, or inner class) has the same name as a
variable declared in an outer scope.
Simply put, when you create a variable with the same name but in other scope it shadows the previous variable.
About the second problem - here is a fine example:
// static1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
void showstat( int curr ) {
static int nStatic; // Value of nStatic is retained
// between each function call
nStatic += curr;
cout << "nStatic is " << nStatic << endl;
}
int main() {
for ( int i = 0; i < 5; i++ )
showstat( i );
}
Output:
nStatic is 0
nStatic is 1
nStatic is 3
nStatic is 6
nStatic is 10
#include<stdio.h>
int main(){
int a=10;
{ printf("%d",a);
int a=20;
printf("%d",a);
}
printf(" %d",a);
return 0;
}
The second a is in a different scope, as you seem to already understand. The "redefinition of a" error only applies when you define two variables with the same name in the same scope.
void main() {
static int a=10;
{
printf("%d ",a);
static int a=20;
printf("%d",a);
}
printf(" %d",a);
}
Again, the a inside the inner block only has scope within that block. If you re-enter the same block, a will continue to have the same value because you declared it as static. However, outside of the block, you will use the value of first variable a. This illustrates the difference between a variable's scope and its lifetime.
Zombie.h has some static member variables. Read.cpp, which includes Zombie.h, knows the values that need to go in those variables. I want read.cpp to set those variables with something along the lines of
int Zombie::myStaticInt = 4;
or
Zombie::setStaticVar(4);
I've tried everything I can think of, including using a public static accessor function and even making the static variables themselves public, but I've been getting a lot of "undefined reference" or "invalid use of qualified-name" errors. By looking into those I found out how to set Zombie.h's private static member variables from Zombie.cpp, but I don't have a Zombie.cpp file, just read.cpp. Can I set them from Read.cpp instead, and if so, how?
// In Zombie.h
class Zombie {
public:
static void setMax(int a_in, int b_in, int c_in) {
a = a_in;
b = b_in;
c = c_in;
}
private:
static int a, b, c;
}
// In read.cpp
#include "Zombie.h"
...
main() {
int Zombie::a; // SOLUTION: Put this outside the scope of main and other functions
int Zombie::b; // SOLUTION: Put this outside the scope of main and other functions
int Zombie::c; // SOLUTION: Put this outside the scope of main and other functions
int first = rand() * 10 // Just an example
int second = rand() * 10 // Just an example
int third = rand() * 10 // Just an example
Zombie::setMax(first, second, third);
return 0;
}
This yields (Updated)
(Move first three lines of main outside of main() to solve this)
invalid use of qualified-name 'Zombie::a'
invalid use of qualified-name 'Zombie::b'
invalid use of qualified-name 'Zombie::c'
You have to define a,b,c somewhere. So far you've only declared them to exist. In some .cpp file, at the outer scope, you need to add:
int Zombie::a;
int Zombie::b;
int Zombie::c;
EDIT Re your edit, you can't put them inside a method. You have to put this at the outermost scope of the .cpp file.
Unlike non-static variables that get storage allocated in every object, static variables must have their storage outside of the class. You do this by creating definitions for the variables in a .cpp file. It doesn't matter which file they go in, although for convenience they should go with the code for the class.
int Zombie::a;
int Zombie::b;
int Zombie::c;
The linker error you're getting is telling you that these lines are missing.
Your problem is you haven't implemented Zombie class yet.
Your code here:
zombie.h
#ifndef ZBE_H
#define ZBE_H
class Zombie
{
public:
static int myStaticInt;
Zombie();
};
#endif
read.cpp
#include <stdio.h>
#include <iostream>
#include "zombie.h"
int Zombie::myStaticInt = 1;
Zombie::Zombie()
{
}
int main()
{
cout << "OOOK: " << Zombie::myStaticInt << endl;
Zombie::myStaticInt = 100;
cout << "OOOK: " << Zombie::myStaticInt << endl;
return 0;
}
I tried this dummy code below to test unnamed namespace.
I have the following output
ctor 1
ctor 0
3
5
I am a bit confused about this.
I was expecting an error from the compiler saying that it cannot resolve
an ambiguity regarding a::m_a. Instead it refers always to the
less nested. Is it always the case? What rules C++ is following?
It seems that the compiler creates variable CMyObj following the order
written on the file. Is this always the case?
is there any way to access the most nested m_a variable
from main()?.
class CMyObj{
public:
CMyObj(int a){std::cout << "ctor " << a << std::endl; }
};
namespace a{
namespace{
int m_a=4;
int m_b=5;
CMyObj m_obj(1);
}
}
namespace a{
int m_a=3;
CMyObj m_obj(0);
}
int main(){
std::cout << a::m_a << std::endl; // which one?
std::cout << a::m_b << std::endl; // how this is possible?
return 0;
}
I don't have C++03 standard with me to check the wording there, so I will quote from FDIS n3290. I think the answer to this question is found in qualified name lookup rules in 3.4.3.2/2:
For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S0(X,m) be the set of all declarations of m in X and the inline namespace set of X (7.3.1). If S0(X,m) is not empty, S(X,m) is S0(X,m); otherwise, S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated by using-directives in X and its inline namespace set.
Now, remember that unnamed namespace is a uniquely named namespace with a using directive.
First look at this simplified code (and my simplified explanation, you can read §3.4.3.2 for the details):
namespace a
{
int x;
}
int main()
{
int i = a::x;
}
Consider what happens when we say a::x. First the compiler enumerates all the declarations of x in a. If it finds an unambiguous x, it finishes successfully. Otherwise it recursively searches the namespaces declared by a using-directive. If it never finds a result, the program is ill-formed.
namespace a
{
int x;
}
namespace b
{
using namespace a;
}
int main()
{
int i = b::x;
}
Here, it doesn't find x in b, so it searches the namespace a (because of the using-directive) and finds it. It should now make sense why this isn't ambiguous:
namespace a
{
int x;
}
namespace b
{
using namespace a;
int x;
}
int main()
{
int i = b::x;
}
Here it finds the x in b and never considers a. Now just consider that an unnamed namespace is actually just a namespace with a unique unknown name:
namespace b
{
namespace
{
int x;
}
// this is what an unnamed namespace expands to (in exposition)
namespace __unique__ {}
using namespace __unique__;
namespace __unique__
{
int x;
}
int x;
}
int main()
{
int i = b::x;
}
Like before, the x in b is found without considering the unnamed namespace. Your code is similar.
I should take time to find the exact definitions in the spec, but when you have an anonymous (unnamed) namespace, the compiler actually generates a mangled name. When you write
a::m_b
in the second std::cout statement, the compiler is automatically substituting the mangled name so you can access it. Incorporating from Gene Bushuyev's subsequent answer:
Now, remember that unnamed namespace is a uniquely named namespace
with a using directive.
In the case of the colliding names, the compiler knows what a::m_a means, so it uses that. It's the one at the top level of the namespace. I don't think there is any way to get to the unnamed namespace copy of m_a at this point.
This page does a decent job of explaining namespaces. Winterdom: On C++ Namespaces
There is no ambiguity because the scope of namespace::<unnamed>::m_a is the outer namespace (namespace::a). There is no way to access namespace::<unnamed>::m_a within the main function and that is why there is no ambiguity. Try the to compile the following code and you'll get the error:
namespace ns{
namespace {
int a = 2;
}
int a = 3;
int c = a;
}
Global variables residing in the same translation unit will be initialized in the order they are declared. Initialization order of global variables declared in different translation units is undefined.