Why is this C++ code WORKING when it SHOULDN'T? - c++

I am learning C++ using Robert Lafore's book ( OOP with C++ ).
In the book, I have encountered this example:
#include <iostream>
#include <conio.h>
using namespace std;
void main ()
{
int numb;
for ( numb = 1 ; numb <= 10 ; numb++ )
{
cout << setw(4) << numb;
int cube = numb*numb*numb;
cout << setw(6) << cube << endl;
}
getch();
}
The variable 'cube' has been declared as int 'inside the loop body'.
int cube = numb*numb*numb;
Since the loop iterates 10 times, the variable 'cube' will also get declared 10 times. 'cube' is accessible inside the loop body no matter what iteration. So, when we enter the loop body for, say, 2nd iteration, 'cube' is already known( because it already got declared during the 1st iteration), and another declaration for 'cube' should give an error of "redefinition". But instead, it builds successfully and debugs without a problem. Why?

The scope of an automatic variable (such as cube) is the block in which it is declared. The block that cube is declared in is the body of the for loop. At the end of each iteration, the cube variable goes out of scope, the next iteration starts and then cube is introduced to the scope again. Logically, there is no clash because no two identifiers cube exist in the same scope - in fact, there is only a single declaration of cube.
It might be worth distinguishing between the declaration of a variable and the creation of an object due to that declaration. There is only one declaration int cube = ...;. It doesn't matter that this piece of code may be reached many times; it's still only one declaration. The rules of the language say that you cannot declare two variables with the same name in the same scope, but that's okay since you're only declaring it once. This is a completely static rule that your compiler is able to analyse.
It just so happens that your declaration is reached 10 times because of your for loop, which means that 10 int objects will be created. Due to the scope of the variable, they won't all exist at the same time. This is not a static property of the program. The compiler cannot in general know beforehand how many times a line of code will be reached.

When you enter the loop a 2nd time, the first cube has gone out of scope so it's all OK.
Two cubes in the same scope would be a problem:
{
int cube = 0;
int cube = 1;
}

You've discovered "Automatic-storage duration".
The variable cube is declared inside the loop. Especially, inside the block-scope of the loop. At the end of the loop, this variable will be destroyed, just like any variable declared in any block-scope, be it a function, a loop, an if/else block, or just a raw block scope that you can declare anywhere in the code using { and }, i.e.:
int main(){
//Beginning of block
{
int cube = 1;
//cube exists and is declared here
}//End of block
//cube is gone here
return 0;
}
So in fact, every iteration of the loop will have its brand new and fresh cube variable.

The variable cube is only used inside the body of the for loop. I am not sure that saying it is declared ten times is correct (a declaration, actually a definition in your case, is a syntactic and static textual portion of source code).
In C++ you can (and you often do) have blocks with local variables. The scope of cube starts at it declaration and ends at the end of the containing block (braces { ... }).
If the type of a defined variable has a constructor, it is called at the definition point. If that type has a destructor, it is called conceptually at the end of the block (figuratively, just before the closing } ....).

The variable will be declared in each iteration of the loop, and then it will go out of scope as the block ({...}) ends, i.e. it will cease to exist. Then on the next iteration it will be declared again, which is not a redeclaration, since it didn't exist. It is said to be a "local variable", in this case local to the block.

As cube is defined inside the cycle body its scope will be that body. So after each iteration completes cube will go out of scope and on the next iteration a brand new cube will be created. This is what happens in theory. It may happen though that the compiler optimizes this code and only ever creates one variable. Either way the code is perfectly valid and will work as excepted.

The variable 'cube' is declared and defined in each iteration. The scope of 'cube' dies with the iteration and new declaration and definition in each loop happens.

Related

Why the variables defined inside a for loop only exist inside of it?

I was reading C++ Primer by Stanley B. Lippman and at the part of flow control it shows an example of a for-loop like this one:
#include <iostream>
int main(void){
int sum=0;
for (int val=1; val <= 10; val++)
sum +=val;
std::cout << sum << std::endl;
return 0;
}
If I try std::cout << val; outside of the for-loop, the IDE gives me an error. But I want to understand why it happens and how it is different from this code:
#include <iostream>
int main(void){
int sum=0;
int val;
for ( val=1; val <= 10; val++)
sum +=val;
std::cout << sum << std::endl;
std::cout << val;
return 0;
}
Where I can actually print the val value without any problem.
Does it have something to do with local variable considering the for-loop a function that we are using inside of the main?
Every variable has scope, which is (loosely speaking) its lifetime.
A variable declared in the head of a for loop has scope limited to the for loop. When control passes out of the loop, the variable passes out of scope. Exactly the same thing happens to variables declared in a function, when control passes out of the function.
Does it have something to do with local variable considering the for-loop a function that we are using inside of the main?
Nothing to do with functions; there are plenty of other ways to get a scope, including a block:
int main()
{
{
int x = 0;
}
std::cout << x; // error
}
And a for loop is another example.
Its deliberate. Its called scope, Whenever you introduce a block { /*stuff here */ } (and a few other places) the variables inside the block are local to the block and supersede (hide) variables of the same name defined outside the block. It helps to ensure block-local code does not tread on other variables. Can be useful when editing an old codebase and you don't want to accidentally use a wider scoped variable.
The concept behind this is called Scope of the variable. Whenever a variable is created a memory location is assigned to it. So in order to optimize the memory usage scope of the variable is defined.
In the first case, the variable is limited only to the for loop. The variable is created inside at the beginning of the loop, utilized inside the loop and destroyed when the execution comes out of the loop.
In second case, the variable is created outside the loop so it persists till the execution of the program and hence you were able to access it even after the loop.
The variable declared inside the for loop is an example of local variable and that declared outside is an example of global variables.
Not only with the loops, the local variables will also be used in if..else blocks, functions and their usage is limited only within the scope.
Hope this answers your question.
Running this exact code does not turn up any errors for me. I get a value of 55 for sum and 11 for val as expected. Because you defined val outside of your for loop but in main, it should be good everywhere within the main() function to the best of my knowledge. As a general rule, if you declare a variable in between two curly braces without any fancy keywords, it should stay valid within those two curly braces (being "local" to that block of code). I am no c++ guru, so there might be exceptions to that (I am also not sure if "if" statements count as code blocks whose locally defined variables only work within the statement).

c++ error int i = 0 not working

For some reason in my c++ code, int i= 0 is not working. In debug mode, it stores 1024 into i after it goes out of scope. When I try to declare it to 0, it doesn't work. i is not a global variable.
void CCurrent::findPeaks()//this checks for peaks in the FFT
{
int localPeakIndx[256]={};
int j=0;
for(int i=0;i<DATASIZE/2;i++)
{
if(magnitude[i]>m_currentValues.AverageMagnitude*3) {
localPeakIndx[j]=i;
j++;
}
}
//i should be out of scope
int startIndx;
int endIndx;
int i = 0;//why does it equal 1024?????? debug*
It is not clear what you mean by "int i= 0 is not working" and "it stores 1024 into i after it goes out of scope". That description is unrealistic and most likely does not take place. After int i = 0 the value of i will be seen as 0, not as 1024.
What you have to keep in mind in this case is that your program has two i variables: one local to for cycle and one declared further down in the surrounding block. These are two different, completely unrelated variables.
Now, MS Visual Studio debugger will show you the values of all variables declared in the current block, even if the execution has not yet reached their point of declaration. Expectedly, variables whose declaration (and initialization) point has not been reached yet are shown with indeterminate (uninitialized) values.
Apparently, this is exactly what happens in your case. Your are looking at the value of outer i before its point of declaration and initialization. Even though name i is not yet visible immediately after the for cycle from the language point of view, the debugger will nevertheless give you "early access" to the outer i. The garbage value of that i at that point just happened to be 1024 in your experiment.
Note that there's certain definitive logic in this behavior. In general case it is not correct to assume that a local object does not exist above the point of its declaration. Being located above the point of declaration in spatial terms does not necessarily mean being located before the point of declaration in temporal terms, which becomes clear once you start using such beautiful feature of the language as goto.
For example, this piece of code
{
int *p = NULL;
above:
if (p != NULL) {
std::cout << *p << std::endl;
goto out;
}
int i = 10;
p = &i;
goto above;
out:;
}
is legal and has perfectly defined behavior. It supposed to output the valid initialized value of i through a valid pointer p, even though the output takes place above the i's point of declaration. I.e. it is possible to end up in the situation when the current execution point is located above the object declaration, yet the object already exists and holds a determinate value. To help you with debugging in such situations the debugger allows you to see the values of all objects that may potentially exist at that point, which includes all objects declared in the current block. In general case the debugger does not know which objects formally exist already and which do not, so it just lets you see everything.
Just a small refinement of what was already said:
The "outer i" is given space on the stack along with all other local variables when the function is entered.
Since the "outer i" hasn't been given a value before the end of the for loop, the debugger is looking on the stack where the value for i ought to be, and showing you what happens to be there.
This comes from the fact that local variables are not initialized.
I bet if you tried to access i from C before the declaration, the compiler would tag that as an error. But the debugger doesn't have such scruples.

Scope of variable

suppose
while(1)
{
{
{
int a=10;
a=5;
}
}
}
now as I cannot refer to "a" after its block's brace. I want to know when control moves up to first brace and then running down visited third brace again will "a" declared again or "a" hold value 5.
A new a variable will be defined in each step of loop.
a will only be declared when you declare it...
You declared it inside an inner scope, so any code referring to a will only be valid inside the same scope. Once you leave that scope, there exists nothing in your program called 'a' any longer. The memory that used to hold the value 5 may now be used by the rest of the program for other purposes.
Logically, the a cant be reference before its declaration, or after the close of the brace pair its declared in. It also gets destructed at the close, but thats a NOP for ints.
Each time around the loop it will be re-initialized to 10.
But, you missed the fun part of the question, about what happens if the declaration doesnt set the value:
while(1)
{
{
int a; // Here Scope Starts
a=5;
}// Here Scope Ends
}
Here, a will be undefined before it is set the first time. But, it will also almost always be in the same place on the stack, so it might possibly retain value from one iteration to the next, if nothing else uses that space. But whether or not it does can be execution dependant, which makes this an exciting source of bugs.
while(1)
{
{
{// Here Scope Starts
int a=10;
a=5;
}// Here Scope Ends
}
}
The variable will logically be reallocated on the stack with each iteration -- in practice, the memory location will simply be reused. But note, in your trivial example, the value of "a" would never "visibly" hold the value of "5" when the loop returns to the declaration on the next iteration because it is explicitly initialized to "10" at the point it is declared. And if C# follows the same practice as Java, it would be implicitly reinitialized to a default value at that point if the compiler does not complain first that an uninitialized variable is being accessed if you do not initialize it yourself.
each iteration of while loop , you will define new variable a and value of "a" change also but if you loop finish by any way you will lose this variable (you can't use it even in same function)!!
a will be declared again.
usually you will define parameter as a in the loop if you do want it to reset each loop so you won't carry values from iteration to iteration.
while(1)
{
{
{
//Define a new `a`
int a=10;
a=5;
}
}
}
But if you wish to use the same parameter and value for all the iterations, you need to define it out side the loop:
int a=0;
while(1)
{
{
{
//`a` will count the number of iterations.
a = a + 1;
}
}
}

Why is this c++ working? (variables with the same name)

Alright, I wanna know why this code is working, I just realized that I have two variables with the same name within the same scope.
I'm using g++ (gcc 4.4).
for(int k = 0 ; k < n ; k++)
{
while(true)
{
i = Tools::randomInt(0, n);
bool exists = false;
for(int k = 0 ; k < p_new_solution_size ; k++)
if( i == p_new_solution[k] )
{
exists = true;
break;
}
if(!exists)
break;
}
p_new_solution[p_new_solution_size] = i;
p_new_solution_size++;
}
The k in the inner for loop shadows (or hides) the k in the outer for loop.
You can declare multiple variables with the same name at different scopes. A very simple example would be the following:
int main()
{
int a; // 'a' refers to the int until it is shadowed or its block ends
{
float a; // 'a' refers to the float until the end of this block
} // 'a' now refers to the int again
}
Alright, I wanna know why this code is working, I just realized that I have two variables with the same name within the same scope.
You seem confused about scopes. They're not "within the same" scope... the for loop's k has it's own nested/inner scope. More importantly, to see why the language allows it, consider:
#define DO_SOMETHING \
do { for (int i = 1; i <= 2; ++i) std::cout << i << '\n'; } while (false)
void f()
{
for (int i = 1; i <= 10; ++i)
DO_SOMETHING();
}
Here, the text substituted by the macro "DO_SOMETHING" gets evaluated in the same scope as i. If you're writing DO_SOMETHING, you may need its expansion to store something in a variable, and settle on the identifier i - obviously you have no way of knowing if it'll already exist in the calling context. You could try to pick something more obscure, but you'd have people using such convoluted variable names that their code maintainability suffered, and regardless sooner or later there would be a clash. So, the language just lets the inner scopes introduce variables with the same name: the innermost match is used until its scope exits.
Even when you're not dealing with macros, it's a pain to have to stop and think about whether some outer scope is already using the same name. If you know you just want a quick operation you can pop it an indepedent (nested) scope without considering that larger context (as long as you don't have code in there that actually wants to use the outer-scope variable: if you do then you can sometimes specify it explicitly (if it's scoped by namespaces and classes, but if it's in a function body you do end up needing to change your own loop variable's name (or create a reference or something to it before introducing your same-named variable)).
From the standard docs, Sec 3.3.1
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the
program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the
same entity. In general, each particular name is valid only within some possibly discontiguous portion of program text
called its scope. To determine the scope of a declaration, it is sometimes convenient to refer to the potential scope of
a declaration. The scope of a declaration is the same as its potential scope unless the potential scope contains another
declaration of the same name. In that case, the potential scope of the declaration in the inner (contained) declarative
region is excluded from the scope of the declaration in the outer (containing) declarative region.
It might sound confusing in your first read, but it does answer your question.
The potential scope is same as the scope of the declaration unless another (inner) declaration occurs. If occurred, the potential scope of the outer declaration is removed and just the inner declaration's holds.
Hope am clear and it helps..
Because you are allowed to have two variables of the same name within the same scope, but not within the same declaration space. The compiler takes the most-local variable of the appropriate name, similar to how you can 'hide' global variables of name X with a member variable of name X. You should be getting a warning though.
In C/C++ the variable scope is limited by the braces so the following code is valid for the compiler:
int k()
{
int k;
{
int k;
{
int k;
}
}
}

Why does using the same count variable name in nested FOR loops work?

Why does the following not give an error?
for (int i=0; i<10; ++i) // outer loop
{
for (int i=0; i<10;++i) // inner loop
{
//...do something
}
//...do something else
}
The way I understand it, variables in braces ({...}) are in scope only within these braces. But the inner loop is inside the braces of the outer loop. So as soon as I declare int i=0 for the inner loop, shouldn't I get an error about multiple definitions?
You are actually making a new variable with the same name as another variable. Since they are in different scopes this is allowed, and the variable in the inner scope "owns" the name. You will not be able to access the outer-scoped i inside the inner scope.
The for loop declaration itself is part of the scope of the for loop, so counts as part of the inner-scope in the case of the second i.
The C++ compiler accepts this as valid, as the scope of the second is only within the { } braces. If you implement the same in C, you will see an error like this:
$ gcc test.c
test.c: In function ‘main’:
test.c:10: error: ‘for’ loop initial declaration used outside C99 mode
test.c:12: error: ‘for’ loop initial declaration used outside C99 mode
This is illegal in most C dialects; it is a legal C++ declaration, and so may be accepted if you are compiling C with a C++ compiler:
for( int i=0; i<5; ++i){}
It is common to have a loop iterator only in the scope of the loop in C++, but C makes sure (specially with the C90, not C99), that the declaration is outside the scope of the loop. Hope that helps ... :-)
So, when you declare another FOR loop within the older one, then the scope start fresh and your code compiles without any error in C++ or C99. This is the usual accepted norm for a scope declaration.
The best way to understand this is to think about everything between the ( and ) when you declare a for loop as being inside the braces of that for loop, at least as it relates to the scope.
To understand this, consider a function in which you have no x variable declared, then the following code inside will give you an error. (We are also assuming that you have no other x variable defined globally.)
for (int x = 0; x < 10; x++)
{
something();
}
x++; // error, x is not defined.
The inner loop starts another level of scoping, for loops start the scope in the loop definition so the second i is in a new scope.
see
http://en.wikibooks.org/wiki/C%2B%2B_Programming/Scope#Scope_using_other_control_structures
ARE YOU SURE YOU DON'T GET AN ERROR WHILE EXECUTING THIS ....?
you are trying to define the two int variable within the same boundary .due to this this will generate the error . in c# if u try out the same code you will get the error
Error 1 A local variable named 'i' cannot be declared in this scope because it would give a different meaning to 'i', which is already used in a 'parent or current' scope to denote something else