Which is faster in following two code snippets? and Why?
Declared loop index variable outside the for statement:
size_t i = 0;
for (i = 0; i < 10; i++)
{
}
and
Declared loop index variable within the for statement:
for (size_t i = 0; i < 10; i++)
{
}
Neither, they are equivalent and will yield the same machine code.
(The compiler will remove the redundant initialization of i twice from the first example.)
Where a variable is declared has very little to do with performance and memory use.
for (size_t i = 0; i < 10; i++) is usually considered the most readable.
for (i = 0; i < 10; i++) has the advantage that you can use the i variable after the loop is done - which makes most sense when the number of iterations is variable.
The only difference is that on the fist one, i is a global variable, and the second one is a local variable only for the loop.
Related
Note: This is coming from a beginner.
Why does the first one outputs 333 and the second one 345 ?
In the second code does it skips over the declaration? I mean it should initialise the "j" variable again like in the first one.
int main() {
static int j =12;
for(int i=0; i<=2; i++) {
j = 2;
j += 1;
std::cout<<j;
}
return 0;
}
int main() {
for(int i=0; i<=2; i++) {
static int j = 2;
j += 1;
std::cout<<j;
}
return 0;
}
static variables are only initialized once (when first used). After that, it behaves as if it is declared somewhere else (I mean, the initialization is ignored). In the second main, the initialization static int j = 2; is executed only the first time, after that, you are incrementing it sequentially (i.e. 2,3,4...)
In the first loop, you set it's value on each iteration, which is not the same as initialization, so it can be run multiple times.
I have found a piece of code in a C++ program, it seems that it loops two times every for() loop in this program, but why does it need this third for in such preprocessor definition?
#define for for(int z=0;z<2;++z)for
It replaces for with for(int z=0;z<2;++z)for. Obviously, that would turn
for (int i = 0; i < N; ++i) {
// ...
}
into
for (int z=0;z<2;++z) for (int i = 0; i < N; ++i) {
// ...
}
Thus creating two nested loops. Without that extra for it would be
for (int z=0;z<2;++z) (int i = 0; i < N; ++i) {
// ...
}
Which is obviously incorrect.
Note that even though it's “correct” in the form you gave in your question, it doesn't mean it's a “good practice”. This is an example of excessive macro abuse and must be avoided. Here is one of the numerous examples how it could go wrong:
for (int z = 0; z < 5; ++z) {
for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
This will expand into
for (int z=0;z<2;++z) for (int z = 0; z < 5; ++z) {
for (int z=0;z<2;++z) for (int i = 0; i < 3; ++i) {
std::cout << z << std::endl; // this will never print 2, 3, 4
}
}
Meaning that you now have four nested loops, and that the inner loop will print the “invisible” z instead of the z you have declared in the outer loop (which becomes the second-level loop in the expanded code).
Another reason: as pointed by #stefan, it's a very bad idea to use keywords or other well-known identifiers as macro names. Makes one think of the infamous #define true false. And, as #HolyBlackCat mentions, it's also undefined behavior, meaning that as far as the standard is concerned, anything could happen. Ranging from the code “seemingly working” to a full-blown World War III with Martians (who invaded Earth to cleanse it from ugly code).
Firstly, that macro is the ugliest thing I've ever seen. I don't recommend ever doing something like this.
The top answer from Sergey Tachenov is really great, but it should also be mentioned that this macro really makes every for loop run twice. This means the doubly nested loops shown below will execute 400 times (not 200 times)! This might be unexpected.
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
// I'll be executed 100 times without the macro
}
}
becomes
for (int z=0;z<2;++z) for (int i = 0; i < 10; i++) {
for (int z=0;z<2;++z) for (int j = 0; j < 10; j++) {
// I'll be executed 400 times with the macro
}
}
It only gets worse from here. Consider an infinte loop like
int some_condition = 0;
for(;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break;
}
}
turns into
int some_condition = 0;
for (int z=0;z<2;++z) for (;;) {
// insert logic here for calculating whether to break out
if (some_condition) {
some_condition = 0; // set back to false for use down the line
break; // gets me out of for(;;)...but the outer loop repeats
}
}
which bumps you out of the inner infinite loop if the condition is met....only to go right back in it. Now you might be stuck in an infinite loop.
Unexpected behavior is a good reason to avoid something, and macro shenanigans like this is very dangerous, and could be a real b**ch to debug. Imagine if some include directive had this ported in several header files deep...
Preprocessor substitution occurs in a single pass and does not support recursion. So the second "for" is probably for some zany idea of chaining existing "for" loops, prepending them with the macro "for" loop portion.
#define for for(int z=0;z<2;++z)for
Thus it replaces
for (int i = 0; i < N; ++i)
{
// ...
}
with
for(int z=0;z<2;++z)
for (int i = 0; i < N; ++i)
{
// ...
}
Which is a pretty crazy use of the preprocessor.
As i prepared some code sample for a small presentation of OpenMP to my teammate i found a weird case. First i wrote a classic loop :
void sequential(int *a, int size, int *b)
{
int i;
for (i = 0; i < size; i++) {
b[i] = a[i] * i;
}
}
A correct OpenMP usage of a for directive is simple. We just have to move int i declaration in for scope to make it private.
void parallel_for(int *a, int size, int *b)
{
#pragma omp parallel for
for (int i = 0; i < size; i++) {
b[i] = a[i] * i;
}
}
But when i wrote the following function, I expected i get a different result of the 2 other due to the shared int jI declared out-of the for loop scope. But using my test framework I don't see the error I expected, an incorrect value at the output of that function.
void parallel_for_with_an_usage_error(int *a, int size, int *b)
{
int j;
#pragma omp parallel for
for (int i = 0; i < size; i++) {
/*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
j *= i;
b[i] = j;
}
}
I have a complete source code for testing, it build with VS'12 and gcc (with C++11 enable) here http://pastebin.com/NJ4L0cbV
Have you an idea of what's the compiler do ? Does it detect the false sharing, does in move int j in the loop due to an optimization heuristic ?
Thank
In my opinion what might be happening is that compiler is doing some optimization. Since in the above pasted code (without cout), the variable j is not being anywhere other than inside the loop, the compiler can put the declaration of j inside the loop in the produced assembly code.
Another possibility is that the compiler might be converting the 3 statements inside the loop into one single statement, i.e. from
/*int*/ j = a[i]; //To be correct j should be declared here, in-loop to be private !
j *= i;
b[i] = j;
to,
b[i] = a[i] * i;
Compiler will do this optimization regardless of whether its an OpenMP code or not.
i'm using visual studio 2010 and when i do something like
for(int i = 0, j = 0; i < 10; i++)
{
if(m_Var == 1)
j++;
}
if(j == 0)//This line errors undeclared identifier
DoSomething();
I have declared j in the for loop so why is it erroring "undeclared identifier"?
another example would be
for(int i = 0; i < 10; i++)
{
m_Var1++;
}
for(i = 0; i < 200; i++)//This line errors undeclared identifier
{
m_Var2++;
}
that code errors even though it is declared in the for loop, but why? is there a way to do this without having to declare i BEFORE the loop but declare it within the loop instead like in the above examples?
In the first example, j only exists in the scope of the loop
for(int i = 0, j = 0; i < 10; i++)
{
if(m_Var == 1) j++;
} // i, j exist no longer
In the second example, the same applies to i. It's scope is the first loop. You can even check it without a loop:
{
int i = 0;
} // end of scope, end of i
i++; // error,
As I recall, some very early versions of C++ had variables defined in for loops scoped to the block containing the loop. In modern C++, the scope is restricted to the for loop itself. For example:
void foo() {
for (int i = 0; i < N; i ++) {
// i is visible here
}
// In very old C++, i is visible here.
// In modern C++, i is not visible here.
}
Visual Studio actually has an option to enable the old behavior; you can turn off "Force Conformance in For Loop Scope", under Configuration Properties --> C/C++ --> Language. The corresponding compiler command-line option is /Zc:forScope-. But unless you specifically need this to compile old code that you can't afford to fix, I strongly recommend leaving it with the default setting, which conforms to the modern C++ rule. If you're writing new code, just follow the modern C++ rule. If you need a variable to be visible outside the loop, then declare it outside the loop.
Because you declare it in the loop so once the loop has finished, your j variable is out of scope. When you declare variables inside the for statement like this
for(int i = 0, j = 0; i < 10; i++)
the variable only has loop scope.
I have declared j in the for loop ...
Yes, you have. And you can only use it in that for loop, because its scope ends at the closing brace of that loop. You cannot use it after that.
If you want to use it afterwards, you must move the scope out a little bit, but not so far that it will affect other stuff (localisation is still a good thing). One method is to use block scope, something like:
{
int i, j; // Scope starts here,
for (i = 0, j = 0; i < 10; i++)
if (m_Var == 1)
j++;
if (j == 0) // still exists here,
DoSomething();
} // and ends here.
This still limits i and j to a specific, small area, but allows j to "escape" from the if statement.
c++ uses block scope for that variable - msdn docs
I have been looking through some code and I have seen several examples where the first element of a for cycle is omitted.
An example:
for ( ; hole*2 <= currentSize; hole = child)
What does this mean?
Thanks.
It just means that the user chose not to set a variable to their own starting value.
for(int i = 0; i < x; i++)
is equivalent to...
int i = 0;
for( ; i < x; i++)
EDIT (in response to comments): These aren't exactly equivalent. the scope of the variable i is different.
Sometimes the latter is used to break up the code. You can also drop out the third statement if your indexing variable is modified within the for loop itself...
int i = 0;
for(; i < x;)
{
...
i++
...
}
And if you drop out the second statement then you have an infinite loop.
for(;;)
{
runs indefinitely
}
The for construct is basically ( pre-loop initialisation; loop termination test; end of loop iteration), so this just means there is no initialisation of anything in this for loop.
You could refactor any for loop thusly:
pre-loop initialisation
while (loop termination test) {
...
end of loop iteration
}
Some people have been getting it wrong so I just wanted to clear it up.
int i = 0;
for (; i < 10; i++)
is not the same as
for (int i = 0; i < 10; i++)
Variables declared inside the for keyword are only valid in that scope.
To put it simply.
Valid ("i" was declared outside of the loops scope)
int i = 0;
for (; i < 10; i++)
{
//Code
}
std::cout << i;
InValid ("i" does not exist outside the loop scope)
for (int i = 0; i < 10; i++)
{
//Code
}
std::cout << i;
It means that the initial value of hole was set before we got to the loop
That means loop control variable is initialized before the for loop .
For C code,
int i=0;
for( ; i <10 ; i++) { } //since it does not allow variable declaration in loop
For C++ code,
for(int i=0 ; i <10 ; i++) { }
You could omit any of the parameters of a for loop.
ie: for(;;) {} is about the same as while(true) {}
It means that the initial value of hole was set before we got to the loop.
Looks like a list traversal of some kind.
Suppose you wanted to
for (hole=1 ; hole*2 <= currentSize; hole = child)
But the value of hole just before the for loop was already 1, then you can slip this initilization part of the loop:
/* value of hole now is 1.*/
for ( ; hole*2 <= currentSize; hole = child)