variable re-identification causing an infinite loop [duplicate] - c++

This question already has answers here:
variable declaration within the while loop C/C++
(5 answers)
Closed 5 years ago.
Why does this code cause an infinite loop:
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
int y = 7;
cout << y << endl;
}
}
yet removing the "int" in the while statement makes it run once normally?
(
#include <iostream>
using namespace std;
int main() {
int y = 5;
while (y < 6) {
y = 7;
cout << y << endl;
}
}
)

In this loop:
while (y < 6) {
int y = 7;
cout << y << endl;
}
The inner y is not accessible in the condition test.
If you remove the int in the loop, you're simply assigning a new value to the variable defined outside while, thus terminating it.
Look up Scope on CppReference.

The behaviour you have observed is called shadowing.
This means that a variable is "shadowed" by another variable in an inner scope.
(iBug has already provided a link to the C++ scope rules)
The outer scope (in your case while(y < 6)) can not access the inner scope (in your case int y = 7;) and vice versa. Both have the same name, but they are completely separate variables in separate scopes.
This is a very common source for errors (you also find a lot of them here) and doesn't only happen with loops and other scope brackets, but also very often with class members. Imagine a class:
class MyClass {
int a;
public:
void getA( int a ) { return a; }
};
getA() defines a parameter a, which shadows the class member a. This is at least bad style, but even more probable a source of errors. We don't know - did you want to return the member a or did you really mean the parameter? So this should be avoided.
Here's a real life example on Stackoverflow - see my comment below the question (regarding the 3rd constructor)
Possibilities to avoid these kind of errors are:
Use highest possible compiler warnings and perhaps even warnings as errors. Compilers can warn about those kind of shadowing issues.
Use a name scheme. A common scheme is members with a m, m_ prefix, a _ suffix and the like. If the member name in the MyClass would have been m_a, this would have reduced confusion. Of course this doesn't help in your example, but it's a good idea nevertheless.

Related

compiler gives uninitialized local variable error despite initialized variable

I'm studying the Declarations in Conditions topics in C++ and faced the below problem.
#include <iostream>
int main() {
int x;
std::cin >> x;
if(int a = 4 && a != x) {
std::cout << "Bug fixed!" << std::endl;
}
}
I declared and then initialized the variable a. In the The C++ Programming Language by Bjarne Stroustrup Ed.2011, it is said:
The scope of variable declared in if statement extends from its point of declaration to the end of the statement that the condition controls.
That's what I did, I declared and initialized the variable a, but when I try to compare it against x, compiler gives uninitialized local variable a used error. Why, what's the problem?
I can do
int a = 4;
if (a != x)
// ...
but I would like to do it in one line if possible.
In the expression inside the if condition
int a = 4 && a != x
what the compiler actually sees is
int a = (4 && a != x)
where the value of a is clearly being used before it's initialized (which is what the error is saying), and is not the intent of the code.
From C++17, you can use if-with-initializer syntax to achieve the effect you want
if (int a = 4; a != x)
// ...

How to reassign Global variables c++ [duplicate]

This question already has answers here:
can't use structure in global scope
(2 answers)
Closed 4 years ago.
Why can't I reassign global variables int x , like i do in python? But works fine if i put it in function?
#include<iostream>
using namespace std;
int x = 30;
x = 40;
int main() {
cout << x;
system("pause");
return 0;
};
Thanks I'm new to c++
At the global scope in C++, you don't assign variables at all. You can only initialize them. The statement x=40 is meaningless because it's not defined when the assignment is going to happen.
What may have confused you is that one of the ways of initializing a C++ variable looks a lot like assignment. You can tell the difference because initialization with = happens in the context of a declaration, so the type name precedes the variable name.
You can assign new values to global variables, if they're not declared const, but this has to happen within a statement block --- That is, inside a function of some sort. main will do for this example.
#include<iostream>
using namespace std;
int x = 30; // this is static initialization
int main()
{
cout << x << '\n`;
x = 40; // this is an assignment
cout << "Now it's " << x << '\n';
cin.ignore(1);
return 0;
};

How is it possible to have two variables with same names - one is global and another one is local? [duplicate]

This question already has answers here:
variables declaration with same name C++
(5 answers)
Closed 5 years ago.
I understand that two variable can be declared of same name in two distinct function.
how can we declare a variable within a function which is already declared in the global scope?
This is called variable shadowing. In C++, you can use scope resolution operator :: to refer to global variable from inside a block. The C language does not have this, however you may use the following technique to access global variable as well:
#include <stdio.h>
int a = 100;
int main(void)
{
int a = 200;
printf("%d\n", a); // prints 200
// anonymous block used to refer to global a
{
extern int a;
printf("%d\n", a); // prints 100
}
return 0;
}
Even this is possible, be wary, that it may confuse other programmers, i.e. it violates "Don't be clever" principle.
For C++ you can always use the resolution operator to specify what scope you are talking about (::)
However in C the rule is that the variable in the context of the more specific scope is used.
int num = 5;
int main()
{
printf("%d\n", num);
int num = 3;
printf("%d\n", num);
return 0;
}
Prints
5
3
Scope of a variable is the part of he code where that variable is visible.
Therefore a global variable is visible everywhere but a local variable is visible only to a particular section of code.
#include <iostream>
using namespace std;
int a=9;
int main()
{
int a =8;
cout<<a<<endl;
cout<<::a;
return 0;
}
In the above c++ code first output is 8 whereas second is 9.
Here both variables were visible in the code but using scope resolution operator you can decide which variable you actually want.
Said in simple terms, if multiple variables in a program have the same name, then there are fixed guidelines that the compiler follows as to which variable to pick for the execution. I'll go over them all in an example below.
Global variables, as the name suggests are declared outside of any function and are accessible in any part of the code. However, in the event of another variable with the same name as the global one, the local variable would get the higher "preference" for the part of the code that comes after it is declared.
For example,
int num = 25;
class Print
{
int num;
Print();
};
Print::Print()
{
num = 98;
}
void PrintNumber(void)
{
int num = 12;
}
int main(void)
{
cout << num << endl;
int num = 34;
cout << num << endl;
PrintNumber();
Print object;
cout << object.num << endl;
}
I've tried to cover every possible scenario, please don't hesitate to inform me if I missed any scenario out. Anyways, the result of this program would be:
25
34
12
98
The first one is the global one; since the variable num of the class Print and the function PrintNumber() is localized to the object of the class and that function respectively, only the global variable is accessible here. Same for the second number, except a local variable with the same number num has a a higher privilege, so it is given a higher accessibility than the global variable (mind my erroneous English, sorry for that). Then when the PrintNumber() function is invoked, it prints the num of that local variable. Finally, an object of class Print will output the value stored in the num of that class.
Hope this answers your question.

how to access a specific scope in c++?

#include <iostream>
using namespace std;
int x=24 ;
int main()
{
int x=0;
{
int x=5 ;
::x= x+2 ;
}
cout<<::x<<endl ;//first
cout<<x<<endl ; // second
return 0;
}
in this simple example i'm using code block and i know i can modify the global variables using Scope resolution operator.
and i modify the global variable in this example but i wonder if there is a way to modify the variables in specific scope like main function (not necessary the( Scope resolution operator) way )
that mean in this example i need the first output is 24 and the next one 7 .
sorry for my english i hope to understand the question
There are no means to access variables from a specific scope in C++.
If you declare an object or a variable in the inner scope with the same name as an object or a variable in the outer scope, then for all intents and purposes that outer scope's object or variable is not directly visible in the inner scope.
If you already have a pointer or a reference to the outer scope's object, of course, you can still access it indirectly. You just cannot access it directly.
This is a fundamental concept of C and C++; but many other programming languages share the same analogous concept.
The scoping rules of C++ are textual and AFAIK you can't do this, as you can't go putting namespaces inside of functions. But introducing a reference with a unique name may help you as a workaround if you find yourself in a bind like this:
#include <iostream>
using namespace std;
int x = 24;
int main()
{
int x = 0;
int & main_outer_x = x;
{
int x = 5;
main_outer_x = x + 2;
}
cout << ::x << endl; //first
cout << x << endl; // second
return 0;
}
That gives you:
24
7
That shouldn't cost any more memory in your generated code, and lets you keep the outer name untouched. Still, likely to be confusing and error prone if you're purposefully having a name collision within a function. This is abstract code so it's hard to criticize, but most concrete code with such a pattern should probably be done another way.

Strange code... Can someone explain me this

Hi I am switching to C++ from C. While reading http://www.gotw.ca/publications/xc++.htm I see this code block.
const int i = 1;
const int j = 2;
struct x
{
int x;
};
namespace y
{
int i[i];
int j = j;
x x;
int y::y = x.x;
};
And I am totally confused about this specially in namespace y section.
Please explain me the behavior of this code and use of namespace. Also I read somewhere that bad use of namespace leading to violating fundamentals of inheritance. Please give me some examples of using namespace brilliantly.
This example is using some horribly obfuscated code to illustrate a point about the scope of names. From C++11 §3.3.6 [basic.scope.namespace] p1:
... A namespace member name has namespace scope. Its potential scope includes its namespace from the name’s point of declaration (3.3.2) onwards ...
point of declaration is defined in §3.3.2 [basic.scope.pdecl] p1:
The point of declaration for a name is immediately after its complete declarator (Clause 8) and before its initializer (if any), except as noted below.
So it is possible to use e.g. the name i from an outer scope in the initializer of something named i in an inner scope. The code in question:
const int i = 1;
const int j = 2;
struct x
{
int x;
};
namespace y
{
int i[i];
int j = j;
x x;
int y::y = x.x;
}
declares:
y::i as an array of 1 int that will be implicitly zeroed (since all static storage duration objects are zero-initialized if they have no explicit initializer),
y::j as an int with initial value 2,
y::x as struct of type ::x that will be implicitly zeroed, and
y::y is an invalid name. If it was simply y, it would be an int with initial value 0, since its initializer y::x.x is implicitly zero-initialized.
Here's a demo (with y::y changed to y) at Coliru.
NOTE: DO NOT EVER WRITE CODE LIKE THIS. The only time using this feature of names even borders on being acceptable is for member initializers in a class constructor. If you do this anywhere else, I will find you. And I will make you pay.
I think there is some problem with your code. The int y::y = x.x; section is wrong as there is no y previous to this and so this statement needs some correction. I am trying to give some basic info about namespace and its usage, hope it helps.
The main purpose of namespaces is to logically group functionality without the need of long names and the option for handy usage via "using". You can also use same name over different namespaces
namespace Color
{
class Add {};
class Multiply {};
};
namespace Dimension
{
class Add {};
class Multiply {};
};
So you can use the same class name Add, Multiply under two namespaces and one thing which you have to remember is that use namespaces only when required otherwise you will spam the global namespace "std" unknowingly which is not conventional.
For using namespace with inheritance you can search for articles in stack over flow and definitely you will get some. Ex: Accessing Parent Namespace in C++
int i[i]; //line 1
It creates an int array of size 1, as the index i is a constant initialized to 1
int j = j; //line 2
It declares and initilizes a variable j to 2(value of constant j) in a namespace y
x x; //line 3
It creates a structure variable x of type struct x ( Note: The structure variable x is different from the int x present inside the structure x, int x is a member of structure x
int y::y = x.x; //line 4
This is syntactically wrong, there is no need to qualify int y with namespace('y'), as it is already present in the namespaace y, So the statement should be
int y = x.x
where x.x represents accessing the data member (int x) of structure variable x created in the line 3
Namespace example Have a look on this example,it helps you to understand namespaces clearly. Refer the link for more examples [link]http://www.cplusplus.com/doc/tutorial/namespaces/
#include <iostream>
using namespace std;
namespace first
{
int x = 5;
int y = 10;
}
namespace second
{
double x = 3.1416;
double y = 2.7183;
}
int main () {
using namespace first;
cout << x << endl;
cout << y << endl;
cout << second::x << endl;
cout << second::y << endl;
return 0;
}
//Output
5
10
3.1416
2.7183
......Hope it helps you....:)