c++ for loop: 'i' was not declared in this scope - c++

bool linear_search(const string A[], int n, string colour, int &count)
{
for (int i = 0; i < n; i++);
{
if (colour == A[i])
{
return true;
}
}
return false;
}
Compiling the above code results in the error 'i' was not declared in this scope for the if statement if (colour == A[i]).
This is really similar to many other for loops I have written, and I don't understand why it is not declared in the scope. Wasn't it declared in the previous line? How do I fix this?

You have a semi colon after your for loop declaration, remove it and you will be fine.

As others have pointed out, the problem is an extra semicolon that prevents your intended loop body from actually being part of the loop. But I want to provide more information on how to catch and avoid this kind of error.
First of all, when I compile the code with the formatting you show, my compiler produces a warning:
main.cpp:130:32: warning: for loop has empty body [-Wempty-body]
for (int i = 0; i < n; i++);
^
You should check to see if you're already getting this or some similar warning, and if so you should make sure to pay attention to warnings in the future. If you're not getting this warning, see if you can increase your compiler's warning level in some way to cause it to produce a warning like this. Enabling and paying attention to compiler warnings can save you a lot of trouble.
Next, I notice that your code is poorly formatted. Poor formatting can hide this sort of error. When I auto-format the code it becomes:
bool linear_search(const string A[], int n, string colour, int &count) {
for (int i = 0; i < n; i++)
;
{
if (colour == A[i]) {
return true;
}
}
return false;
}
This formatting makes the extraneous semicolon much more obvious. (It also suppresses my compiler's warning about the empty body, since the compiler assumes that if you put the empty body on a separate line then you really mean for it to be empty.) Using automatic formatting avoids the problems of inconsistent formatting and ensures that the formatting is consistent with the actual meaning of the code. See if your editor provides formatting support or see if you can integrate an external formatter like clang-format.

Are you sure you need ; in this line? for (int i = 0; i < n; i++);

you ended for loops block by adding a ; after for loop
for (int i = 0; i < n; i++);
remove this semicolon.

I had a similar problem but there was an "if" statement before my variable declaration in front of a "for" loop, the error was the same. Just in case that somebody googled it and didn't mention something like that:
if (someVar!=1) // an "if" statement that reduces the scope of "var"
//some comment line
//some other comment line
double var = 0.0;
for (size_t i = 0; i < length; i++) {
var *= 0.5; // Error appeared here
}

Related

Why does a for loop invoke a warning when using identical code?

I think that following two codes are identical. but upper one has C4715 "not all control paths return a value" problem and other doesn't.
Why this warning happens?
int func(int n){
for(int i=0; i<1; i++){
if(n == 0){
return 0;
}
else {
return -1;
}
}
}
int func(int n){
if(n == 0){
return 0;
}
else {
return -1;
}
}
The compiler is trying to be helpful, and failing. Pretend for a moment that the code inside the loop was just if (n == 0) return 0;. Clearly, when n is not 0, the loop will execute once and then execution will move on to the next statement after the loop. There's no return statement there, and that's what the compiler is warning you about. It just isn't smart enough to see that the code inside the loop always returns.
So, possibly, add a return 0; statement after the loop. That might make the compiler happy. But it also might make the compiler (or some other compiler) give a different warning about "unreachable code", because that new return statement can't actually be reached. This stuff is hard to analyze, and compilers often get it wrong.
Because warnings don't promise to only flag incorrect code. Nor do they promise to flag all incorrect code. It's not possible to be completely accurate.
It seems like the part of the compiler that issues C4715 assumes that a for loop with an end condition ends in some cases, and doesn't try to calculate if it will always return early.
My first thought is that the loop cannot act.
You initialize the for loop with int i = 0 then give bounds of i < 1 with an action if i++
Given i is type int with step of 1, it can never loop.

name lookup of `a' changed for new ISO `for' scoping

I am trying to troubleshoot this error I get in c++. I've looked at similar questions on StackOverflow, but I can't seem to find the error for my particular solution. I have no idea why it doesn't work, nested for loops work fine this way from my knowledge. Let me know if you have a solution.
NOTE: This is just a code snippet. All variables are defined above. I get the error on line 7.
Here is the exact error message:
50 C:\Users\ryang\Desktop\check install\Untitled1.cpp name lookup of `a' changed for new ISO `for' scoping
Code:
for(int a = 0; a < 500; a ++)
assets[a][0] = temp + temp2;
for(int b = 1; b < 6; b ++)
{
userAssets >> temp >> temp2;
if(temp == "CorporateIT")
assets[a][b] = temp2;
else
{
numWorkstations[a] = b;
break;
}
}
}
When you place a variable in a for loop it is defined only inside that for loop. So when you have:
for(int a = 0; a < 500; a ++)
assets[a][0] = temp + temp2;
The for loop ends at the semicolon here and as such the variable a is now not in scope.
What you need is your for loop to be enclosed with braces to avoid this. I'd suggest always using braces around for loops for this reason, my companies coding standards explicitly demand this to avoid running into the exact problem you encountered here.
I think you forgot the open brace ({) after the first for loop.

C++ character variable value of '\x1'

I'm failing to understand why would the loop exit at the value of character variable i = '\x1'
#include <iostream>
using namespace std;
int main()
{
char i;
for (i = 1; i < 10, i++;)
{
cout << i << endl;
}
return 0;
}
Can somebody please explain this behavior ?
This is wrong
for (i = 1; i < 10, i++;)
/* ^ should be ; */
You only declared 3 regions for the loop, but put your increment statement in the middle area, and left your increment area empty. I have no idea which statement in the middle area your compiler will choose to execute. Best not to try to be cute and deceive your compiler. Let alone some colleague who will read your code years from now and go WTF???
A for loop has 3 distinct areas delimited by semi-colons:
The initialization area. You can declare as many variables in here as you want. These can be delimited by commas.
The test area. This is where an expression goes to test if the loop should continue.
The post loop area. This region of code gets executed after every loop.
Try to keep it simple. If it is going to be more complicated then use a while loop.
The reason that i ends up being 1 is that when i++ is zero, which terminates the loop, then i will become 1 (That is what the form of the ++ operator you used does). As the other answered have pointed out, once you fix your code by moving i++ out of the condition by replacing the comma with a semicolon, then i will make it all the way to 10 as desired.
for (i = 1; i < 10; i++)
You wrote for statement wrong.

Unreachable code in for loop increment?

I'm getting a C4702: unreachable code warning in a for loop; the strange thing is that - by breaking apart the components inside the parens - the warning points to the increment part. Here's a sample program that demonstrates this error:
int main()
{
int foo = 3;
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
return 0;
}
I can't figure out what's wrong with this line, because the for loop looks very straight-forward.
You have a stray semicolon in your if-statement:
if (foo == 4);
Recall that for loops have the following structure:
for (initialisation; condition; increment/decrement)
statement
Execution will proceed in the following order:
initialisation
condition; if false then end
statement
increment/decrement
Go to step 2
If the compiler is warning about the increment/decrement being unreachable, it means that something before it is causing execution to always skip it - in this case, the stray semicolon causes the break to always execute, jumping out of the loop prematurely.
for (int i = 0;
i < 999;
i++) // warning on this line
{
if (foo == 4);
{
break;
}
}
This is same as
for (int i = 0;
i < 999;
)
{
if (foo == 4);
{
break;
}
i++; /* Note the increment here */
}
So anyways you are going to break because of the if(foo == 4); so i++ is not reachable
The problem (i.e. the unintended ;) is already described in two answers.
I just like to add that you should take a look at your compiler options setting. Many compilers can detect such "strange looking" code and give you a warning. For instance:
Warning: "empty body in an 'if' statement"
Further the compiler can be configured to treat all warnings as errors.
In other words - the compiler options can often help you finding "unintended code" so that you avoid wasting time.
BTW - the eclipse editor can even give a "suspicious semicolon" warning as soon as you type such an if-statement.

Simple loop, which one I would get more performance and which one is recommended? defining a variable inside a loop or outside of it?

Variable outside of the loop
int number = 0;
for(int i = 0; i < 10000; i++){
number = 3 * i;
printf("%d",number);
}
or Variable inside of the loop
for(int i = 0; i < 10000; i++){
int number = 3 * i;
printf("%d",number);
}
Which one is recommended and which one is better in performance?
Edit:
This is just an example to exhibit what I mean, All I wanna know is if defining a variable inside a loop and outside a loop means the same thing , or there's a difference.
Time to learn something early: any optimization you could make on something like this will be irrelevant in the face of printf.
Printf will be very, very slow. You could quintuple the math and get no measurable speed decrease. It's just the nature of printing to the terminal.
As for your edited question, there is no difference defining it in the loop or out. Imagine that
for (i = 0; i < 500; i++) {
int a = i * 3;
}
is just the same as
int forloop::a; // This doesn't work, the idea is to show it just changes the scope
for (i = 0; i < 500; i++) {
a = i * 3;
}
They will produce identical code, unless you start needing to use that variable outside of the loop it is defined in, because it is defined in the local scope of the loop. So...more like this:
int forloop::a; // Still not valid code, just trying to show an explanation
namespace forloop {
for (i = 0; i < 500; i++) {
a = i * 3;
}
} // namespace forloop
If this is unclear please let me know I'll go into more detail or explain differently.
Do not bother you with performance at first: make it safe before everything.
I would just quote Scott Meyers (Effective C++) for your concern:
"Postpone declarations as far as you can".
Thus, the second pattern is safer.
Example:
int j = 0;
for(int i = 0; i < 10000; i++){
j = 3 * i;
printf("%d",j);
}
...
// Use of j out of control!!!
int k = j * 5;
Now with the second pattern:
for(int i = 0; i < 10000; i++){
int j = 3 * i;
printf("%d",j);
}
...
// j not declared at this point.
// You get informed of the mistake at compile time, which is far much better.
int k = j * 5;
You do have a C++ tag, and you mention "declaring a string" in the question. Therefore there might be a performance difference (and yes, the printf could swamp it). Declaring a non-simple variable means calling a constructor, which might mean a non-trivial amount of work. In that case, declaring it inside of the loop could be hiding significant work in what appears to be an innocent declaration.
In general, the answer is that if you really care about performance - and treating the sample code as only an example of the difference between two places to declare a variable - then for non-simple variables, it is better to declare it outside the loop, unless the semantics require a fresh version of a temporary at each iteration.
There are likely many other places first to look at if performance is an issue, but one consideration is always moving loop invariants out of loops, especially if it is much easier for you to tell that it is invariant than for the compiler. And what looks like a declaration, can, in C++, fall into that category.
If, for (silly) example, you have
int k = 43;
for ( int i = 0; i < N; ++i )
{
int j = 17 + k; // k was previously defined outside the loop, but doesn't change in it
l = j * j; // l was also declared outside the loop
}
any good optimizing compiler can recognize that k is constant, and that j is always assigned 60, and l is assigned 3600 N times, and the loop can simply be removed and replaced with a single assignment to l. Here k and j are both loop invariants.
But a not-quite-so-good compiler might miss even one link in that chain, and wind up creating the loop.
It gets harder for the compiler to figure things out when you have
Foo k( 43 ); // a class that takes an int argument to its constructor
for( int i = 0; i < N; ++i )
{
Bar j( k ); // a Bar takes an int argument, adds 17 and stores it.
l = j.squared();
}
Same invariants. Not as easy to detect without looking inside the workings of bar; and if the constructor and squared method aren't inline, we've just made it slower.
In this case, printf("%d", i * 3) would be better than defining the variable at all.
To answer your question and not nitpicking:
The difference between the 2 variants is, that you are declaring your variable number in different "variable environments" - by which I mean that the scope changes. A variable environment is given by your curly braces { ... }. Everytime you open a new curly brace like this { ... { ... } ... }, you declare a new variable environment inside the old one, which means, that if you declare numbers like so:
{ ... { int numbers; ... } ... }
this variable will only be visible or existent in the innermost environment. So
{ ... { int numbers; ... } ... do_something(numbers); ... }
will give a compiler error.
And to your concerns about performance: Neither variant is better performing. Most, if not all compilers will give the same assembly.