The below code generates an error when i run it but if i declare at-least one variable outside the loop the code works fine.Why can't i declare both the variables in the loop itself?
Error:
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
for(int j=0,int i=0;i<4&&j<2;i++,j++)
{
cout<<"Hello"<<endl ;
}
getch() ;
return 0 ;
}
Works Fine:
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
int i ;
for(int j=0,i=0;i<4&&j<2;i++,j++)
{
cout<<"Hello"<<endl ;
}
getch() ;
return 0 ;
}
You can, but the notation for declaring two variables in a single declaration is like this:
int j=0, i=0;
with no second int.
(This is actually what your second version is doing; you might think it's assigning the already-declared i, but actually it's declaring a new one, whose scope is the for-loop.)
Because that's how the Standard defines the syntax. There's nothing "wrong" in particular with the idea, but apparently it was decided that you can only have one declaration in the initialization part.
If you want to declare multiple variables, use a comma to enumerate them (but this way, you can only declare variables of the same type):
for (int i = 0, j = 10; i < 10; i++, j--)
However, I'm not sure you should be doing this. After a certain point, this evolves into an unreadable mess.
Note that the given answers "only" handles making multiple variables of the same type.
If, for some bizarre reason, you would need to do multiple types, this is valid (though awful):
for(struct {int a; double b} loop = {0, 1.5}; loop.a < loop.b; loop.a++)
{
// Awful hacks
}
Related
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.
I stumbled recently in this problem
for(int i=0,n=v.size(); i<n; i++) {
...
P2d n = ... <<<--- error here
}
the compiler was complaining about the fact that the n local variable has been already defined, despite that the open brace looks like it should start a new scope.
Indeed the standard has a special wording for this and while the code compiled fine with g++4.6.3, it complains with more recent versions and other compilers.
What is the rationale (if there is any) behind this special rule?
To be more clear: the standard explains that this is not permitted and I've no questions about the technical reason for which that's an error: I was just wondering why the committee decided to use special extra rules instead of just creating another nested scope when seeing the opening brace (like it happens in other places).
For example to make the code legal you can just wrap the body with two brace pairs instead of one...
Please also note that braces after for/while/if, while considered good practice, are not mandatory and not part of the syntax, but still a scope containing the loop variables exists (therefore using function definition as another example where the scope of the locals is the body of the function is not relevant: a function body is not a statement and braces are mandatory).
In the C++ syntax the body of a for is just a statement; however if this statement happens to be a braced group then it gets a special handling in for/while/if (that doesn't happen when you use a braced group as statement elsewhere in the language).
What is the reason for adding this extra complication to the language? It's apparently not needed and just treating the braces as another inner scope seems (to me) simpler.
Are there use cases in which this simpler and more regular approach doesn't work?
Note that I'm not asking opinions. Either you know why the committee took this decision (requiring also a quite elaborate wording in the standard instead of just having the body as a regular statement with the regular handling of a brace enclosed block when used as statement) or you don't.
EDIT
The "single scope" view for the syntax is for me unnatural but technically possible for the for statement that can be rationalized as a single block with a backward goto statement, but it's hard to defend in a very similar case for the if statement:
if (int x = whatever()) {
int x = 3; // Illegal
} else {
int x = 4; // Illegal here too
}
but this is instead legal
if (int x = whatever()) {
int z = foo();
} else {
int z = bar();
}
So are the condition, the then part and the else part of an if statement the same scope? No because you can declare two z variables. Are they separate scopes? No because you cannot declare x.
The only rationalization I can see is that the then and else part are indeed separate scopes, but with the added (strange) rule that the variable declared in the condition cannot be declared in the scope. Why this extra strange limitation rule is present is what I'm asking about.
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
Can be translated from the point view of recent compilers into:
int i = 0;
{
MyObject o1;
Label0:
MyObject o2; //o2 will be destroyed and reconstructed 10 times, while being with the same scope as o1
i++;
if (i < 10)
goto Label0;
}
This is the answer to your last question mark at the end, they didn't add something complicated, just used goto to label in the same scope, and not goto to out of the scope and then enter to it again. I don't see clear reason why it's better. (While it will do some incompatibility with older codes)
The semantics are not special for the for loop! if (bool b = foo()) { } works the same. The odd one out is really a { } block on its own. That would be rather useless if it didn't introduce a new scope. So the apparent inconsistency is due to a misplaced generalization from an exceptional case.
[edit]
An alternative view would be to consider an hypothetical, optional keyword:
// Not a _conditional_ statement theoretically, but grammatically identical
always()
{
Foo();
}
This unifies the rules, and you wouldn't expect three scope (inside, intermediate,outside) here either.
[edit 2] (please don't make this a moving target to answer)
You wonder about lifetime and scopes (two different things) in
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
Let's generalize that:
MyObject o2; // Outer scope
int i = 0;
for (MyObject o1; i<o1.fooCount(); i++) {
std::cout << o2.asString();
MyObject o2;
}
Clearly the call to o2.asString() refers to the outer o2, in all iterations. It's not like the inner o2 survives the loop iteration. Name lookup doesn't will use names from the outer scope when the names aren't yet defined in the inner scope - and "not yet defined" is a compile-time thing. The repeated construction and destruction of the inner o2 is a runtime thing.
Look at it this way:
A pair of braces allows you to hide variables visible inside an enclosing pair of braces (or globally):
void foo(int n)
{
// the containing block
for (int i = 0; i < n; ++i)
{
int n = 5; // allowed: n is visible inside the containing { }
int i = 5; // not allowed: i is NOT visible inside the containing { }
}
}
If you think about it this way you realize there are no special rules here.
The brackets ({}) deliminate a section of code as a block. Everything in this block is within it's own local scope:
int main(int argc, char** argv)
{
int a = 5;
std::cout<<a<<std::endl // 5
{
int a = 10;
std::cout<<a<<std::endl //10
}
std::cout<<a<<std::endl // 5
}
But wait, there is something else in that code...
int main(int argc, char** argv)
{
}
This is similar to the structure of a for loop:
for (int i = 0 ; i < 5; i++)
{
}
The function definition has code outside the {...} block too!
in this case, argc and argv are defined, and they are local to the scope of the function just like the definition of i in the above for loop.
In fact you can generalise the syntax to:
definition { expression }
Where the entirety of the above is within the scope.
In this case, the 'raw' brackets ({}) form the same structure but with an empty definition statement.
edit:
to answer your edit, in:
int i = 0;
for (MyObject o1; i<10; i++) {
MyObject o2;
}
the constructor for o2 is looped over for each loop, while the the constructor for o1 isn't.
for loop behavior goes as follows (where XXX is the current block being executed:
init
for(XXX; ; ){ }
test loop exp
for( ;XXX; ){ }
execute block
for( ; ; ){XXX}
final operation
for( ; ;XXX){ }
Back to 2.
As there is there was the c tag I would answer from that perspective. Here is an example:
#include <stdio.h>
int main(void) {
int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
for (int i = 0, n = 8; i < n; i++) {
int n = 100;
printf("%d %d\n", n, a[i]);
}
return 0;
}
It compiles without issues, see it working at ideone (C99 strict mode, 4.8.1).
C standard is clear that both scopes are considered as separate, N1570 6.8.5/p5 (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.
There is a warning, but only with the -Wshadow option, as expected:
$ gcc -std=c99 -pedantic -Wall -Wextra -Wshadow check.c
check.c: In function ‘main’:
check.c:7: warning: declaration of ‘n’ shadows a previous local
check.c:6: warning: shadowed declaration is here
The loop control variables (i and n in this case) are considered part of the for loop.
And since they are already declared in the loop's initialization statement, most attempts (other than re-defining by using nested braces) to re-define them within the loop results in an error!
I cannot tell you why there is just one scope opened by the for loop, not a second one due to the braces. But I can say what was given back then as the reason for changing where that single scope is: Locality. Take this kind of pretty standard code:
void foo(int n) {
int s=0;
for (int i=0; i<n; ++i) {
s += global[i];
}
// ... more code ...
for (int i=0; i<n; ++i) {
global[i]--;
}
}
Under the old rules, that would have been illegal code, defining i twice in the same scope, the function. (In C back then, it was even illegal because you had to declare variables at the beginning of the block.)
That usually meant you’d leave out the declaration in the second loop – and run into problems if the code with the first loop was removed. And whatever you did, you had variables with a long time to live, which as usual makes reasoning about your code harder. (That was before everyone and their brother started to consider ten lines a long function.) Changing for to start its own scope before the variable declaration here made code much easier to maintain.
You problem is that the definition part of the for is considered inside the scope of the for.
// V one definition
for(int i=0,n=v.size(); i<n; i++) {
...
// V second definition
P2d n = ... <<<--- error here
}
#include "average.c++"
#include "name.c++"
class Grade {
public:
Grade() {}
void searcharray(Name *array[]) {
int i;
for(i = 0; i <= 10; i++){
printf("%s", array->name);
}
}
};
int main() {
int i;
char line[64];
Name *names[10];
for(i = 0; i < 5; i++){
scanf("%s", &line);
names[i] = new Name(line);
}
Grade *test;
test = new Grade();
test->searcharray(names);
}
This code gives the error
"grade.c++ in member function 'void Grad::searcharray(Name*)':
grade.c++:11:25: error: request for member 'name' in ' array', which is of pointer type 'Name*' (maybe you meant to use '->' ?)"
I need help making this work. I am guessing it is something simple like extending the class like you would in Java but not sure how this works in c++.
I am assuming you can pass an array of objects to a class like you would in C with just an array.
The root to my question is to find a solution and to get a reason for this code being wrong.
Your code can be substantially improved by taking advantage of the Standard library. The problem with your initial code was that you were doing array->name where array was a C-style array (technically the pointer into which it decayed). An expression like that isn't possible unless you obtain the pointer at the index first:
array[i]->name;
Moreover, the for loop in which that line was written is traversing the array 1 too many times. The conditional statement i <= 10 should be i < 10 so you won't dereference an address past the end of the array.
Anyway, instead of showing your code with the corrections, I thought I might as well show you what it should look like if you use vectors, memory-management, and std::string. I hope this helps:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class Grade
{
public:
Grade() { }
static void searcharray(const std::vector<std::unique_ptr<Name>>& array)
{
for (const auto& obj : array)
{
std::cout << obj->name;
}
}
};
int main()
{
std::string name;
std::vector<std::unique_ptr<Name>> names;
while (std::cin >> name)
names.push_back(std::unique_ptr<Name>(new Name(name)));
// names.push_back(std::make_unique<Name>(name))
Grade::searcharray(names);
}
Note that I also made searcharray static since it has nothing to do with a given instance of Grade.
As others have pointed out the problem is that you're using a parameter declared Name *array[] like array->name.
Remember that C++ built on top of C, which follows a rule 'declaration mimics use', which means that the way a variable is declared looks like the way it is used. So with the declaration:
Name *array[]
The way you get a name out of this is:
*array[i]
And name is a member of Name so you have to get a Name object first. Then you can tack on member access:
(*array[i]).name
And then you can use the -> shortcut where (*x).y is the same as x.y:
array[i]->name
Other issues:
Your code appears to be heavily influenced by the style of code required for the 1989 or 1990 version of C. You should try to avoid that as it makes writing C++ code much worse than it has to be.
You declare a Grade * and allocate it immediately. You can combine the declaration with initialization into:
Grade *test = new Grade();
But you don't need to use a pointer anyway: use Grade test; (and if you did need a pointer then you should use a smart pointer. Never use 'naked' new.)
Similarly you can avoid new when you create Names.
Name names[10]; // assuming that Name is default constructible
for(...) {
...
name[i] = Name(line);
}
You should avoid a fixed size array here. Instead you should default to using std::vector:
std::vector<Name> names;
for (...) {
...
names.push_back(Name(line)); // or in C++11 names.emplace_back(line);
}
You should declare the variable i as part of the for loop, not as a variable outside it:
for (int i=0; i<10; ++i)
When you read input you should avoid scanf and fixed sized buffers. Instead, if you're reading lines you should probably start off with std::getline and std::string.
std::string line;
while (std::getline(std::cin, line)) { // read as many lines as there are, not just 10 no matter what
names.emplace_back(line);
}
This question already has answers here:
Can I declare variables of different types in the initialization of a for loop? [duplicate]
(5 answers)
Closed 9 years ago.
I'm trying to declare and initialize variables of different type inside a for-scope.
Something like:
for (int i = 0, double u = 1; i < 10; ++i)
{...}
but the compiler (gcc) returns me an error.
I know that can perform initialization using the same type variables (example), but I don't know how is it possible do it with different ones.
Of course I can declare the variable outside the loop:
double u = 1;
for (int i = 0; i < 10; ++i)
{...}
but I'm looking for something clean because the variable u is used only inside the for-scope.
So,
Can I do it?
If so, how can I?
Its not allowed to declare more then one type in a declration statement. The only way to contain u within the scope remotely close to the for loop would be something like that:
{
double u = 1;
for (int i = 0; i < 10; ++i)
{
//some code
}
}// u's scope will end here
Of course creating a new scope will do, but writing a function is more common way.
void foo()
{
// So this function deals with loop and does something with 'u'.
double u = 1;
for (int i = 0; i < 10; ++i)
{ ... }
}
It is hard to say if you really need a function, but I believe it is a very clean and natural way.
You have to think as if you are declaring these variables in another part of the code.
You can declare as many variables as you want in the same line always if they share the type.
You can declare:
int a=3, b=3;
But the ';' points the end of this type declaration. If you try to do:
int a=3, double b= 3.4;
As you wish the compiler translate that as a "double" declaration of the b variable. First the compiler recognize it as an int, but then you are specifying another type. Thats why you can't do that. If you try to do it as your compiler wish (type variable=value; another_type another_variable = another_value;) you'll break the for structure.
Alright, I'm guessing this is an easy question, so I'll take the knocks, but I'm not finding what I need on google or SO. I'd like to create an array in one place, and populate it inside a different function.
I define a function:
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
That's an approximation to what my code is doing, but regardless, shouldn't be running into any overflow or out of bounds issues or anything. I generate an array:
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
then I want to pass it to someFunction
someFunction(result);
When I set breakpoints and step through the code, upon entering someFunction, results is set to the same address as result, and the value there is -1.000000 as expected. However, when I start iterating through the loop, results[n] doesn't seem to resolve to *(results+n) or *(results+n*sizeof(double)), it just seems to resolve to *(results). What I end up with is that instead of populating my result array, I just get one value. What am I doing wrong?
EDIT
Oh fun, I have a typo: it wasn't void someFunction(double results[]). It was:
void someFunction(double result[])...
So perhaps this is turning into a scoping question. If my double result[16] array is defined in a main.cpp, and someFunction is defined in a Utils.h file that's included by the main.cpp, does the result variable in someFunction then wreak havoc on the result array in main?
EDIT 2:
#gf, in the process of trying to reproduce this problem with a fresh project, the original project "magically" started working.
I don't know how to explain it, as nothing changed, but I'm pretty sure of what I saw - my original description of the issue was pretty clear, so I don't think I was hallucinating. I appreciate the time and answers...sorry for wasting your time. I'll update again if it happens again, but for the meantime, I think I'm in the clear. Thanks again.
Just a point about the variable scope part of the question - there is no issue of variable scope here. result/results in your someFunction definition is a parameter -> it will take on the value passed in. There is no relation between variables in a called function and it's caller -> the variables in the caller function are unknown to the called function unless passed in. Also, variable scoping issues do not occur between routines in C++ because there are no nested routines. The following pieces of code would demonstrate scoping issues:
int i = 0;
{
int i = 0;
i = 5; //changes the second i, not the first.
//The first is aliased by the second i defined first.
}
i = 5; //now changes the first i; the inner block is gone and so is its local i
so if C++ did have nested routines, this would cause variable scoping
void main()
{
double results[16];
double blah[16];
doSomething(blah);
void doSomething(double * results)
{
//blah doing something here uses our parameter results,
//which refers to blah, but not to the results in the higher scope.
//The results in the higher scope is hidden.
}
}
void someFunction(double results[])
should be exactly equivalent to
void someFunction(double *results)
Try using the alternative declaration and see if the problem persists.
To me it seems that your code should simply work.
I just tried this in g++ and worked fine. I guess your problem is elsewhere? have you tried the snipped you posted?
#include <iostream>
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
int main()
{
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
someFunction(result);
for(int i = 0; i<16; i++)
std::cerr << result[i] << " ";
std::cerr << std::endl;
}
Have you perhaps double defined your results array in a couple places and then accidently refered to one copy in one place and another copy elsewhere? Perhaps the second is a pointer and not an array and that is why the debugger is confused?
To ensure this problem doesn't occur, you should never use global variables like that. If you absolutely must have one, put it in a namespace for clarity.