Error Redeclaring a for Loop Variable Within the Loop

Why declaring a variable inside a loop does not mean re declaring the variable each time loop is entered

You're smashing together two related but different concepts and thus your confusion. But it's not your fault, as most of the didactic material on the matter doesn't necessarily make the distinction between the two concepts clear.

  1. Variable scope: This is the region of the source code where a symbol (a variable) is visible.

  2. Object lifetime: this is the time during the runtime of the program that an object exists.

This brings us to other two concepts we need to understand and differentiate between:

  1. A variable is a compile-time concept: it is a name (a symbol) that refers to objects
  2. An object is an "entity" at runtime, an instance of a type.

Let's go back to your examples:

int main()
{
int x{};
int x{};
}

Here you try to declare 2 different variables inside the same scope. Those two variables would have the same name inside the function scope, so when you would "say" the name x (when you would write the symbol x) you wouldn't know to which variable you would refer. So it is not allowed.

int main()
{
while(true)
{
int x{};
}
}

Here you declare one variable inside the while body scope. When you write x inside this scope you refer to this variable. No ambiguity. No problems. Valid code. Note this discussion about declarations and variable scope applies at compile-time, i.e. we are discussion about what meaning has the code that you write.

When we discus object lifetime however we are talking about runtime, i.e. the moment when your compiled binary runs. Yes, at runtime, multiple objects will be created and destroyed in succession. All of these objects are referred by the symbol x inside the while body-scope. But the lifetimes of these objects don't overlap. I.e. when you run your program the first object is created. In the source code it is named x inside the while-body scope. Then the object is destroyed, the loop is re-entered and a new object is created. It is also named x in the source code inside the while-body scope. Then it is destroyed, the while is re-entered, a new object is created and so on.


To give you an expanded view on the matter, consider you can have:

A variable which never refers to an object

{ // not global scope
int a; // <-- not initialized
}

The variable a is not initialized, so an object will never be created at runtime.

An object without a name:

int get_int();

{
int sum = get_int() + get_int();
}

There are two objects returned by the two calls to the function get_int(). Those objects are temporaries. They are never named.

Multiple objects instantiated inside the scope of a variable.

This is an advanced, contrived example, at the fringe of C++. Just showing that it is technically possible:

{

int x;

// no object

new (&x) int{11}; // <-- 1st object created. It is is named `x`. Start of its lifetime

// 1st object is alive. Named x

x.~int(); // <-- 1st object destructed. End of its lifetime

// no object

new (&x) int{24}; // <-- 2nd object created. Also named `x`

// 2nd object alive. Named x

} // <-- implicit end of the lifetime of 2nd object.

The scope of x is the whole block delimited by the curly brackets. However there are two object with different non-overlapping lifetimes inside this scope.

Re-declaring variable inside for loop in C

In C language, the scope of statement is nested within the scope of for loop init-statement.

According to Cppreference :

While in C++, the scope of the init-statement and the scope of
statement are one and the same, in C the scope of statement is nested
within the scope of init-statement
.

According to stmt:

The for statement

for ( for-init-statement conditionopt ; expressionopt ) statement

is equivalent to

{
for-init-statement
while ( condition ) {
statement
expression ;
}
}

except that names declared in the for-init-statement are in the same declarative-region as those declared in the condition,
and except that a continue in statement (not enclosed in another
iteration statement) will execute expression before re-evaluating
condition.

Why does redeclaring the C variable from a loop not affect the loop?

This is due to scope. Each time you use braces {} you generate a new scope for the program. Anything initialised in that scope will be removed once the scope is exited, which for you is every loop when it exists to check the loop condition.

Using what I have just said we see that you are reinitialising i by saying int i = 10; This means you have created a new variable, called i, which has the value 10, within this scope. You can get your desired result by just writing i = 10; as it will first look inside the scope for the variable, then it will loop in the next scope above where it will find it in your for loop.

EDIT:

Commenting further on this, it means that you can have the same name for multiple variables as long as they are in different scopes from each other. Like so :

#include <stdio.h>
int main()
{
int x = 10;
printf("x = %d\n",x); //check x value equals 10

for(int i = 0; i < 10; i ++)
{
int x = i;
printf("x = %d\n",x); //a new variable, also called x, now outputs x = i;
}

printf("x = %d\n",x); //check x value returns to the original when scope is left
return 0;
}

Why redeclaring variables in body is forbidden but inside a for loop isn't, with c++?

One word: scope.

A {} pair creates a new scope. Scopes can be nested.

In the first example, there are two separate a variables being declared in the same scope, which is not allowed.

In the second example, there is only one a variable being declared, not two variables (so no conflict to begin with) in the scope of the for loop's body. Just because a loop runs multiple times does not mean multiple variables are declared. Since a is local to the loop body, every iteration of the loop allocates, uses, and frees the a variable each time (in reality, the compiler optimizes to reuse the same memory each time).

Why are variables declared inside a loop body not considered a redeclaration?

Because it's a different z, not the same one. You can see that it's a different one if you write a function that closes over it:

for (let i = 1; i<5; i++) {
const z = 'dwan' + i;
setTimeout(() => {
console.log(z);
}, i * 200);
}

Why doesn't the C compiler give a redeclaration error inside a for loop body?

C++ and C make a distinction here. According to C11 (n1570) §6.8.5 ¶5, emphasis mine:

An iteration statement is a block whose scope is a strict subset of
the scope of its enclosing block. The loop body is also a block whose
scope is a strict subset of the scope of the iteration statement
.

Which translates to this for a for loop:

{
declaration
while ( expression) {
statement
expression ;
}
}

Anything you put in the statement part can hide whatever is introduced in the declaration. Now, C++(17, n4659) explicitly says something similar at [stmt.for]/1. But it also goes on to add:

except that names declared in the init-statement are in the same
declarative region as those declared in the condition,

So here the second i is indeed an attempt at a re-declaration. The above may sound confusing (names declared in the condidion!?), but the "condition" here is defined like this ([stmt.stmt]/1):

condition:
expression
attribute-specifier-seq decl-specifier-seq declarator brace-or-equal-initializer

It's that which allows while loops like this (C++ only):

while (T t = x) statement 

And you may not re-declare t inside the statement of the while loop.


Alternatively, the entire conclusion I reach is summarized in [stmt.iter]/3 (thank you @T.C.):

If a name introduced in an init-statement or for-range-declaration is
redeclared in the outermost block of the substatement, the program is
ill-formed.

How does a for loop allow redeclaration of a variable?

The variable j exists only per iteration, i.e. in each iteration a variable j is declared, assigned, used and then discarded and the next iteration begins and the process repeats and so forth. hence you don't get the same compilation error as the first example snippet.

Variable redeclaration in c in loop and outside loop?

In order to understand your problem, also called variable's scope, let's see to the following sample program:

#include <stdio.h> 

int main(int argc, char *argv[])
{
int I = -1;
for (int I = 0; I < 3; I++) {
printf("%d\n", I);
}
printf("%d\n", I);
{
int I = 200;
printf("%d\n", I);
}
return 0;
}

As you can see I declared the variable I three times.

When declared into the loop the result will be the Printing of the following values:

0
1
2

After the for loop when I print again the I variable now I refer to the variable declared outside the for loop, the first one I declaration so the result will be:

-1

Now if I open a new scope with the curly braces and I declare a new variable with the same name but with a different value I will get:

200

I hope my description about the variable's scope is now clear



Related Topics



Leave a reply



Submit