C++ Confusing scope of redeclared variables in for loop - c++

The following while loop does not terminate. This is because the variable x is being re-declared inside the while loop. But I don't understand why in the second iteration onward, the statements x<10 and y=x considers the x defined in the outer scope and not the x defined in the block scope in the following statement.
Is this because once the first iteration ends, the x defined in the block scope is destroyed and the loop begins to execute fresh?
#include<iostream>
int main () {
int x = 0, y;
while(x <10 ){
y = x;
std::cout<<"y is :"<< y <<std::endl;
int x = y + 1;
std::cout<<"x is :"<< x <<std::endl;
}
std::cout<<"While loop is over"<<std::endl;
}

Every iteration the while loop evaluates the outer scope x and y is assigned the value of the outer scope x. After that another x is defined in the inner scope which is what the second std::cout uses, but the program makes no other use of the inner x
In the code below I replaced the inner x with z but otherwise the behavior is identical. The only difference is that there is not a second x within a more inner scope to hide the outer one:
#include<iostream>
int main () {
int x = 0, y;
while(x <10 ){
y = x;
std::cout<<"y is :"<< y <<std::endl;
int z = y + 1;
std::cout<<"z is :"<< z <<std::endl;
}
std::cout<<"While loop is over"<<std::endl;
}
Below I have an example that is intended to clear the confusion. In the inner scope x is not being "re-declared", a new x is being declared and it goes out of scope after the }:
#include<iostream>
int main () {
int x = 1;
{
int x = 2;
std::cout << x << '\n'; // 2
}
std::cout << x << '\n'; // 1
}

Yes, you understand it correctly. So every time when compare in while, it is using the outer x.
while (x < 10) {
y = x; //Here the x is the outer one. The inner one does not exist yet.
std::cout << "y is :" << y << std::endl;
int x = y + 1; // From here, x will refer to the inner one.
std::cout << "x is :" << x << std::endl;
// inner x is destroyed.
}

Related

the scope and priority of variable in c++

Could anybody explains to me why the result is 2, which x is using and why.
auto x = 0;
int f(int i){
auto x = 1;
{
static auto x = 0;
x += i;
}
return x;
}
int main() {
cout << f(1) + f(2) <<endl;// result 2
return 0;
}
The inner x shadows the outer one, but the mutations only apply to the inner most scope
int f(int i){
auto x = 1; // consider this "x1"
{
static auto x = 0; // this is "x2"
x += i; // mutates "x2" but not "x1"
}
return x; // return "x1" which is still 1
}
Therefore
f(1) + f(2) // 1 + 1 == 2
This is all about variable shadowing.
The innermost x in function f is shadowing the automatic x in that function. So that function is equivalent to
int f(int){
auto x = 1;
return x;
}
Note furthermore that the x in my abridged version shadows the one at global scope.
The function f is further abbreviated to
int f(int){
return 1;
}
and now the program output should be obvious.
In fact this function
int f(int i){
auto x = 1;
{
static auto x = 0;
x += i;
}
return x;
}
can be rewritten like
int f(int i){
auto x = 1;
return x;
}
because the static variable x declared in this block scope
{
static auto x = 0;
x += i;
}
is not used outside the block and does not influence on the returned value of the function. The only side effect of this code block is potential overflowing of the static signed integer variable x that has undefined behavior.
So the both function calls f(1) and f(2) returns 1 and as a result the expression f(1) + f(2) yields 2.
In the program there are declared three variables x. The first one in the global name space
auto x = 0;
The second one in the outer-most block of the function f that hides the declaration of the variable x in the global name space.
auto x = 1;
And the third one is declared in an inner block of the function f
{
static auto x = 0;
x += i;
}
that is not visible outside this inner block.

Why is int x{ y = 5 } possible?

int main() {
int y;
int x{ y = 5 };
//x is 5
}
How is this possible, since y = 5 is not a calculable expression?
Also, why doesn't the compiler or IDE complain about main() not returning an int?
How is this possible, since y = 5 is not a calculable expression?
It is an assignment, and assignments yield values, i.e. the "cv-unqualified type of the left operand", see [expr.ass/3]. Hence y = 5 results in y, which is 5, which is used to initialize x.
With respect to your second question, see cppreference on main (or [basic.start.main/5]):
The body of the main function does not need to contain the return statement: if control reaches the end of main without encountering a return statement, the effect is that of executing return 0;.
Hence, compiler or IDE warning you about a missing return statement at the end of main would be plain wrong. Admittedly, the fact that you should always return objects from non-void functions execpt main is kind of... well, for historical reason I guess.
I will start from your last question
Also, why doesn't the compiler or IDE complain about main() not
returning an int?
According to the C++ Standard (6.6.1 main function)
5 A return statement in main has the effect of leaving the main
function (destroying any objects with automatic storage duration) and
calling std::exit with the return value as the argument. If control
flows off the end of the compound-statement of main, the effect is
equivalent to a return with operand 0 (see also 18.3).
And relative to this question
How is this possible, since y = 5 is not a calculable expression?
From the C++ Standard (8.18 Assignment and compound assignment operators)
1 The assignment operator (=) and the compound assignment operators
all group right-to-left. All require a modifiable lvalue as their left
operand and return an lvalue referring to the left operand.
Sp this declaration
int x{ y = 5 };
can be equivalently split into two statements
y = 5;
int x{ y };
Moreover in C++ you can even to make a reference to the variable y the following way
int &x{ y = 5 };
Here is a demonstrative program
#include <iostream>
int main()
{
int y;
int &x{ y = 5 };
std::cout << "y = " << y << '\n';
x = 10;
std::cout << "y = " << y << '\n';
}
Its output is
y = 5
y = 10
You may this declaration
int x{ y = 5 };
rewrite also like
int x = { y = 5 };
However take into account that there is a difference between these (looking similarly as the above declarations) two declarations.
auto x{ y = 5 };
and
auto x = { y = 5 };
In the first declaration the variable x has the type int.
In the second declaration the variable x has the type std::initializer_list<int>.
To make the difference more visible see how the values of the objects are outputted.
#include <iostream>
int main()
{
int y;
auto x1 { y = 5 };
std::cout << "x1 = " << x1 << '\n';
auto x2 = { y = 10 };
std::cout << "*x2.begin()= " << *x2.begin() << '\n';
std::cout << "y = " << y << '\n';
return 0;
}
The program output is
x1 = 5
*x2.begin()= 10
y = 10
The operator=() results in a value, which is the value assigned to the variable. Because of this, it is possible to chain assignments like this:
int x, y, z;
x = y = z = 1;
If you take a look at the documentation on cppreference, you'll see that operator=() return a reference to the object that was assigned. Therefore, a assignment can be used as an expression that returns the object that was assigned.
Then, it's just a normal assignment with braces.

Returning 0 after functions are called without "return(0);"

I'm having a small issue in trying to figure out why a zero is printed out at the end of my while loop.
#include <iostream>
using namespace std;
int x;
int CountDown(int x);
int CountUp(int x);
int main()
{
int toCountUp = CountUp(x);
cout << x << endl;
}
int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
My best response would be that it is in the condition of the while loop. Or a return status from the function/main being fulfilled, but I don't have a return on there, and I know a function doesn't require a return statement but in this while loop I want there to be a integer returned, do I need to make the function void so there will be no return? But what about the parameter x that I need for the while loop?
code output:
0
1
2
3
4
5
6
7
8
9
10
0 < ---- this is the number I do not want.
Thinking about it, it has to be a value returned at the end of the function, any ideas?
This outputs the values 0 through 10:
int toCountUp = CountUp(x);
Then, this outputs 0:
cout << x << endl;
The method does not change the value that is passed to it, it uses its own local copy of that variable.
—It's mainly because you are printing cout << x << endl; twice. Once in the int CountUp(int x) function itself, but again in the main function.
—It could've printed any given value of x at this point, but since you're setting x=0 outside of the While{} loop in the int CountUp(int x) function, it's printing 0 at the end after the function call is executed.
*int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}*
—Is there a reason why you are setting x=0 within the function? since you're passing x as a parameter in the function call, and adding 1 to it in the While{} loop until it's x<= 10? Asking because you're not returning x back to the main() function.
—In case you wanted to use the end value of x to countdown using CountDown(x), you may like to reset x=0 in the main() function after calling the block—
*int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}*
At last 0 is printed in main() function because x is declared global.
If you want latest x after loop got over to be printed in main() then you should reference variable and don't declare it globally.
int CountUp(int &); /* function prototype*/
Since passed variable(actual argument) and reference variable having the same memory So modification will affects in calling function.
int CountUp(int &x) { /* catch with reference variable so that modification affects in calling function also */
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
First read Shadowing variables and What's the difference between passing by reference vs. passing by value?
The int x parameter of CountUp shadows the global variable int x so inside CountUp, the only x is the parameter.
int CountUp(int x)
int x defines x as passed by value, so it is a copy of the x used to call CountUp in main. This different x is counted up to 10 and then discarded.
the global int x has static storage duration and is default initialized to zero for you. Do not try this trick with a variable with Automatic duration because unless it has a constructor that does something useful, the contents are uninitialized and their value is undefined.
Sideshow issue:
A function that has a non-void return type MUST return a value on ALL paths. If it does not, you have Undefined Behaviour and the compiler can generate hopelessly invalid code that can get you even if the bad path is not taken. Don't smurf with Undefined Behaviour, as it might crash the program or do something hilariously wrong, but it might also look like it works until it suddenly doesn't at a really bad time.
Solutions:
void CountUp(int & x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
}
Passes x by reference allowing global x and the local x to be one and the same and returns nothing.
Usage would be
CountUp(x);
Not so useful in the asker's case because it doesn't leave a toCountUp.
int CountUp(int x)
{
x = 0;
while(x <= 10)
{
cout << x << endl;
x++;
}
return x;
}
Makes a copy if the provided x, operates on the copy, and then returns x. Usage would be
int toCountUp = CountUp(x);
And will set toCountUp to 10 higher than the global x.

While Loop that increments a variable to a point

My goal for this program is to get input from the user for value 'y' and then multiply that value by 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and then print the 10 results. Right now, when the user enters a value for 'y', the program just returns a list of zeros. Any idea what I'm doing wrong?
#include <iostream>
using namespace std;
int main(){
int x;
int y;
int z;
x = 0;
z = x * y;
cout << "enter y" << endl;
cin >> y;
while (x < 10) {
cout << z << endl;
x = x + 1;
}
}
The problem you have is that you don't actually calculate z inside the loop, so it will always be the value you calculated outside the loop. Statements and expressions can't be done retroactively.
But you have a worse problem than that, because you use y before you initialize it, which leads to undefined behavior.
You need to change the location of the y input to be before the calculation of z that should be inside the loop
The statement z = x * y should be inside your while loop for it to work.
What is happening now is that,each time it is printing the same value of z which is calculated initially as x(which is 0) and y(which is some garbage value as it has not been initialized) to give 0
The first problem occurring in your code is that try to assign z by multiplying x with y, but y is not assigned to a certain value => ERROR! That means you should get your user input before you assign z.
You may wonder why you get ten outputs of '0': Inside the loop you only print the value assigned to z to the console but z is already assigned before and not changed during the repetition.
#include <iostream>
using namespace std;
int main(){
int x;
int y;
int z;
x = 0;
z = x * y; // y is never assigned to a value
cout << "enter y" << endl;
cin >> y; // y got assigned here!
while (x < 10) {
cout << z << endl; // z stays the same in the loop
x = x + 1;
}
}

Variables out of scope in main when called by reference by a function in C++

I have made the following code, whose output should generate a point uniformly at random on the unit circle centered at the origin:
#include "unif.h"
#include <iostream>
#include <cmath>
using namespace std;
void point_on_circle(double& x, double& y)
{
double r;
do
{
double x = unif(-1.,1.);
double y = unif(-1.,1.);
double r = x*x + y*y;
}
while (r >=1.0);
x = x / sqrt(r);
y = y / sqrt(r);
}
int main()
{
cout << "Pair of points on the circle found is " << x << " and " << y << endl;
cout << "Let's verify: x^2+y^2=" << x*x+y*y << endl;
return 0;
}
The header "unif.h" is just a file that contains a function void unif(double x, double y), that produces uniformly random numbers in the interval (x,y), and it works perfectly (already tested).
The problem is that when I build the program then it gives me (of course) the error in the main:
"error: 'x' was not declared in this scope"
which is clear since of course x is defined outside the main and never defined in main(). I cannot figure out how to tell the compiler that the values of x and y found by the function point_on_circle should be "carried" inside the main. How could I fix this code?
Thanks in advance
In your main method you did not declare a variable called x nor y. Moreover, you also have scoping issues in your point_on_circle(double& x, double& y) function with the variable r.
Please review C++ scoping.
Because you defined x in the do-while loop, so you cannot use it outside the loop, since those definitions hide the parameters x and y. Define it before the loop:
void point_on_circle(double& x, double& y)
{
double r;
do
{
x = unif(-1.,1.);
y = unif(-1.,1.);
r = x*x + y*y;
}while (r >=1.0);
x = x / sqrt(r);
y = y / sqrt(r);
}
You have a few issues.
1) you need to declare x and y inside main.
2) you never, ever actually call point_on_circle. At all.
3) finally, as others noted, you mask parameters x and y in your do loop.
With all of that said, it looks like you're attempting to find a random point on the unit circle. with that in mind, I would remove the do loop entirely and just do this:
void point_on_circle(double& x, double& y)
{
double r;
x = unif(-1.,1.);
y = unif(-1.,1.);
r = x*x + y*y;
x = x / sqrt(r);
y = y / sqrt(r);
}
It gives the exact same result while avoiding a (potential) endless loop, and certainly avoids useless extra processing.