Archived

This topic is now archived and is closed to further replies.

GamerSg

Why does this compile?

Recommended Posts

Thanks to this compiling, i messed up my FYP presentation today when the spells failed to cast.
for(int i=0;i<watever;i++)
{
}
for(int k=0;k<numOfSpellObjs;k++)
{
	if(spellObjs[i].active)
	{
		spellObjs[i].updateAnimation();
	}
}
i is not defined anywhere as a global in my source files. Shouldnt the compiler return an error. When i highlight i and select goto definition, i get a list of 4 header files like commctrl.h, mapidefs.h, wabdefs.h and atlhtml.h where there is a definition of i. But i have not included these files at all. [edited by - GamerSg on October 21, 2003 12:02:15 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
shouldn''t one write simple and easily followed code that one KNOWS works - after testing of course

Share this post


Link to post
Share on other sites
Yeah i should have.

But it had always worked until i made a few changes the night before or maybe in the early morning is a better description.

The spells had always worked and i was extremely tired as i was rushing to compile all the files and burn them. By 2am, the last thing i wanted to do was to go and test something which had always worked. Anyway, the presentation is over and the spells part was the only blunder.

What im concerned is that why the code compiles. With the exception of the 4 header files, which i have not included at all, i is not defined.

Share this post


Link to post
Share on other sites
i is defined by the first for loop, It hangs around until the end of the block containing the for loop. The same would be true of k. dunno if this is the correct behavior but that''s what it does.

Share this post


Link to post
Share on other sites
This is an example of Visual C++''s for loop scope conformance deviation. All versions of Visual C++ .NET have a compiler option that allows you to enable proper scoping in for, but it''s disabled by default for each project. Just enable it, and life will be good again.

Share this post


Link to post
Share on other sites
things declared in a for loop dont exactly act like you would think, their scope isn't the for loop, it's the block the for loop is in. (vc++ specific, im unsure about other compilers)

void main()
{
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
{
}
}
for(int i=0;i<2;i++)//error, i already exists within this scope
{
for(int j=0;j<2;j++)// but j is ok
{
}
}
}


[edited by - Raptor85 on October 21, 2003 12:13:30 PM]

Share this post


Link to post
Share on other sites
Well if its supposed to be around for the whole block, i should be getting an error if i do this.

void uselessLoops()
{
for(int i=0;i<whatever;i++)
{
//do stuff

}
for(int i=0;i<crap;i++)//should get an error here

{
}
}


But even this compiles. Guess it''s an issue only with VS. BTW, how do i enable the "proper" for loop in VS.NET?

Share this post


Link to post
Share on other sites
like merlin9x9 said it''s a compiler bug (or failed atempt at ''embrace and extend''? you be the judge...). Use a standards compliant compiler like gcc and it wouldn''t have happened.

Naku is also right, but according to the standard (can''t remember if it''s ISO or ANSI) a variable declared inside the parameter brackets of a for loop is in scope only in the for loop. It makes more sense that way i think - if you are declaring a counter variable you probably don''t want to use it outside the loop anyway.

Share this post


Link to post
Share on other sites
do this to get around that visual studio bug


#define for if(false) { } else for


there is a very good reason why the compiler behaves like that, but I''ve forgetten why and dont'' feel like looking it up.

Share this post


Link to post
Share on other sites
Thanks for all the replies. Just made me realise that i still have so much to learn from even for loops which was something i had learned the first day i learnt programming.

Share this post


Link to post
Share on other sites
As was mentioned but apparently ignored, VC++ 7 and 7.1 both have a compiler switch to govern this behaviour; they default to the old, pre-standard behaviour, but can be made to use the new, standard behaviour.

Share this post


Link to post
Share on other sites
quote:
Original post by mrbastard
like merlin9x9 said it's a compiler bug (or failed atempt at 'embrace and extend'? you be the judge...). Use a standards compliant compiler like gcc and it wouldn't have happened.

Naku is also right, but according to the standard (can't remember if it's ISO or ANSI) a variable declared inside the parameter brackets of a for loop is in scope only in the for loop. It makes more sense that way i think - if you are declaring a counter variable you probably don't want to use it outside the loop anyway.


Just get Visual Studio .NET 2003. You can upgrade from .NET 2002 for cheap.

if not, there is one very handy way around this for your noncompliant compiler (if it doesn't have the option to fix scope)

#define for if(0) ; else for   


this makes it so whenever you use for it gets put in the else statement of an if which is always false. since scoping works properly with if statements in older visual c++ compilers, this allows you to work with for statements as they're SUPPOSED to be, and it'll happen all without costing you anything.

(the reason it's in the else statement and not in an if(1) is so that if the for statement is in a one line if with an else, there won't be any problems, otherwise the else would be matched up with the if in the #define

[edited by - Polymorphic OOP on October 21, 2003 12:33:16 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Or instead of an ugly macro hack, just get into the habit of declaring variables outside of your for loop:

int i;
for(i=0; i<whatever; ++i)
{
}

Share this post


Link to post
Share on other sites
If you do that, you run the risk of accidentally using that variable again without reinitializing it. The standard is that way it is because that''s the right way. Use the macro hack inside another macro hack that will enable it only on non-conformant compilers. Any modern compiler will optimize away the if-else part of it.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Or instead of an ugly macro hack, just get into the habit of declaring variables outside of your for loop:



That makes it behave like it does in visual studio, no matter what compiler you use. And that''s exactly what the OP wanted to avoid. There''s a much bigger chance of having bugs if the variable is accessible outside the loop, than if the for loop behaves the correct way.

The ugly macro hack does the opposite, makes the for loop follow the c++ standard.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
or, instead of using absolutely meaningless array index variables, why not?:

for(int wateverIndex=0; wateverIndex < watever; wateverIndex++)
{
}
for(int spellObjIndex=0; spellObjIndex < numOfSpellObjs; spellObjIndex++)
{
if( spellObjs[spellObjIndex].active )
{
spellObjs[spellObjIndex].updateAnimation();
}
}

it''s amazing how many logic errors good coding practice can help prevent.

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
or, instead of using absolutely meaningless array index variables, why not?:

for(int wateverIndex=0; wateverIndex < watever; wateverIndex++)
{
}
for(int spellObjIndex=0; spellObjIndex < numOfSpellObjs; spellObjIndex++)
{
if( spellObjs[spellObjIndex].active )
{
spellObjs[spellObjIndex].updateAnimation();
}
}



because noone can be bothered to type out a huge variable name when a single letter would suffice and everyone knows that 'i' is usually an array index so it doesn't really cause any confusion. and if the compiler was standards compliant (by default) then there wouldn't've been a problem.


[edited by - necromancer_df on October 21, 2003 6:36:33 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Anonymous Poster
Or instead of an ugly macro hack, just get into the habit of declaring variables outside of your for loop:

int i;
for(i=0; i{
}



That''s almost always the wrong thing to do. The macro, though strictly illegal, is by far the better solution.

Share this post


Link to post
Share on other sites