Why Not Local Loops? Reasons Explained

In summary, this conversation is about whether or not it's acceptable to only define an index for an array in a for loop, as opposed to also declaring the index variable within the loop. Some people believe this is bad practice, as it increases the scope of the variable to be used within the loop. However, other people argue that this is a good way to keep the code organized and prevent variables from being accidentally used outside of the loop.
  • #1
jk22
729
24
Once i did the following :

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

Hence with the i defined only in the loop and the professor told me we shall never do that.

Do you know any reason ?

Thanks.
 
Technology news on Phys.org
  • #2
jk22 said:
Once i did the following :

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

Hence with the i defined only in the loop and the professor told me we shall never do that.

Do you know any reason ?
The only reason I can think of is that compilers prior to the C99 spec didn't allow intermingling of declarations and executable statements, as you have in the for loop above. Other than that, I can't think of any reason why the above wouldn't be fine.
 
  • #3
I can't see anything really wrong with this.
It sets up a loop which you want to iterate 100 times, and there could be a perfectly good reason why you want to do that.
Possibly the tutor is objecting to the fact that no matter what goes on inside the loop, it's still always going to execute 100 times.
It's generally more useful to have a loop which will terminate depending on some condition occurring inside the loop.
 
  • #4
jk22 said:
Once i did the following :

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

Hence with the i defined only in the loop and the professor told me we shall never do that.

Do you know any reason ?

Thanks.

Some instructors think that you should write a WHILE loop instead (and escape it on the appropriate condition), but really, people do the above all the time and I really don't have a problem with it. If you want to escape the loop before it goes 100 times, you can just use a break statement.
 
  • #5
Yes often we want to iterate an indexed array and at some condition being found escape with an index set of where we exitted the loop.
 
  • #6
The OP didn't say anything about exiting the loop early. If I know I'm going to want to exit early, I normally write it as a while loop, myself.

I took the question to be about declaring i as part of the loop initialization, which restricts its scope to inside the loop. I consider this to be a good thing, if you don't intend to use i outside the loop. It's like declaring local variables for a function instead of using global variables.

If you want to use a variable named i somewhere else in the program, you have to declare it again outside the loop, and this means you actually have two separate variables named i. Changing the value of i inside the loop doesn't change its value outside the loop, and vice versa.
 
  • Like
Likes DrClaude and jedishrfu
  • #7
I tend to use a for loop when I have something that is indexed and a while loop when I don't rather than having a while that increments an index. It just depends on which is more elegant to me at the time I'm writing the code.
 
  • #8
Yes, there is an aspect of programming as an art form, rather than 'engineering'.
However in most employment, the employer doesn't give a damn as long as it works.
 
  • Like
Likes jedishrfu
  • #9
rootone said:
However in most employment, the employer doesn't give a damn as long as it works.

Someone will probably chime in about coding standards at many companies / organizations...
 
  • #10
jk22 said:
Once i did the following :

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

Hence with the i defined only in the loop and the professor told me we shall never do that.

Do you know any reason ?

Thanks.
I think the take-home lesson here is that there are different programming standards in different circumstances. Often, if you are working in a team, there will be standards that define style in an attempt to make all code look as though it came from the same author. The notion is that it can then be more readily reviewed or enhanced by other team members. In a lot of cases, I question the value of these standards - at some point, you need to be able to read anyone else's code and the main impediment to that is hardly in the style.
There are also safety standards. For example, as I recall the MISRA standards, used in the automotive industry, advise against making variable declaration with statements such as the "for" statement. Again, the objective is to make the code more reviewable - especially in an environment where a bug could cost a life.
 
  • #11
jtbell said:
Someone will probably chime in about coding standards at many companies / organizations...
Sure, I've worked for three companies, in my current position, I help set the standard. Your professor is wrong, in the real world you're supposed to declare a variable in as small of a scope as possible. In C, it's traditional to declare all of your variables at the top of your program, that allows it to just move the stack pointer once, but that's because C didn't make much use of an optimizer. C++ uses an optimizing compiler, so it works better if you limit your variables to only the scope that they are needed in. You're professor's opinion is about a decade out of date.

This has been standard at all companies: DON'T REUSE VARIABLES! That's the biggest reason to declare it inline, to make sure that there isn't already an i somewhere.
 
  • #12
IIRC, C99 allowed declarations inside loops, in part, to help deal with "locality" issues. Commodity CPUs have "local" buffers with names like L2 or L1. Program code in those buffers can be accessed and executed quickly. Otherwise, the code from somewhere in slower RAM has to be accessed over and over again. The cost of accessing that code over and over again can be large when the code makes millions of iterations of a loop. Data may have the same problem, you can create a memory object that is too large to fit in the local buffers at one time. e.g. a gigantic array with millions of elements.

IF this sounds at all interesting try:
http://lwn.net/Articles/250967/ Start of the article there are 7 parts
http://lwn.net/Articles/252125/ Part that speaks to CPU caches.
 
  • #13
jk22 said:
Hence with the i defined only in the loop and the professor told me we shall never do that.

Do you know any reason ?
If you break out of the loop for some reason and you want to know afterwards if you did and for what value of i it happened, you may not be able to access a "localized" i. You can work around that, however, with a bit of thought and design before you code.

I must admit to being an old-fashioned ANSI C programmer, so an "inline" declaration does not seem natural to me.
 
  • #14
MISRA-C is a standard that is often applied to C code in airplanes and automobiles. The habit of declaring the index as you suggest would make it tempting to violate mandatory MISRA rule 21 (and maybe others):
"Identifiers in an inner scope shall not use the same name as an identifier in an outer scope, and therefore hide that identifier".

I am not sure what the history and rationalization of this rule is, but there is it and we often have to follow it.
(see http://home.sogang.ac.kr/sites/gsinfotech/study/study021/Lists/b7/Attachments/91/Chap%207.%20MISRA-C%20rules.pdf )

PS. I advise against using a generic loop index like i or j. Better is row_index, column_index, student_index, etc. whatever you are looping through.
 
Last edited by a moderator:
  • #15
FactChecker said:
PS. I advise against using a generic loop index like i or j. Better is row_index, column_index, student_index, etc. whatever you are looping through.
Agreed, i, j, x are nice and everyone uses them. It took me 10 years of writing code before I really got into the habit of explicitly naming variables like that, it's much easier to maintain later.
 
  • #16
In C++ in case you have same name variable in different scopes, the scope operator :: can be used. But it's true, using i,j,... is a bad habit, when writing small test codes maybe.
 
  • #17
From "Code Complete," by Steve McConnell,
Loop control variables in simple loops may have simple names. i, j, and k are customary.
...
If the variable is to be used outside the loop, it should be given a more meaningful name than than i, j, or k.
He also says that if the loop is longer than a few lines, or you have nested loops, it's better to use a more meaningful name for the loop index(es).
 
  • Like
Likes Jaeusm
  • #18
jk22 said:
In C++ in case you have same name variable in different scopes, the scope operator :: can be used. But it's true, using i,j,... is a bad habit, when writing small test codes maybe.
Only if you name the scopes, which isn't done very often.

Also, in a loop, you should use ++i instead of i++.
 
  • #19
newjerseyrunner said:
Also, in a loop, you should use ++i instead of i++.
That depends on the language. C and C++ are rather different languages, despite suggestions from management such as "We need to hire a C/C++ programmer!"

In C, the canonical form for a for loop is to use for (variable_name=initial; !final_condition; variable_name++)[ { ...} . Using ++variable_name in lieu of variable_name++ is a sign that the programmer may be doing something suspicious. It's exactly the opposite in C++. Using ++variable_name is the canonical form in C++; uing variable_name++ is a sign that something dubious might be happening.
 
  • #20
For the scope operator I thought naming were not mandatory ::i is just the previous scope ?

As for D H i didn't know that point just i read once about the border effect that since the stack of the arguments is reverse we could obtain weird results

i=10;
Prinft ("%d,%d.",i,++i)

Would print 11,11 ?
 
  • #21
jk22 said:
For the scope operator I thought naming were not mandatory ::i is just the previous scope ?
There is no way in C or C++ to access a hidden local variable. In C++, ::variable_name accesses the global variable of the given name in the global namespace. It does not provide access to some hidden local variable.
i=10;
Prinft ("%d,%d.",i,++i)

Would print 11,11 ?
There's no telling what that will print. The above code invokes undefined behavior. It might print 11,11. Then again, it might print 10,11. There's no telling. It might even make demons fly out of the programmer's nose (the so-called in nasal demons). The above could even result in a call to erase_hard_drive().
 
  • Like
Likes jk22
  • #22
I'm learned something new, but I'm a bit deceived, about the scope operator. I thought it was working hierarchically, going to outer and outer scope, so that we could have written ::i, ::::i, aso, but ::i directly access the global scope ?
 
  • #23
It doesn't work that way. Consider the following:
Code:
#include <iostream>
int ii = 1;
int main()
{
   int i = 2;
   { 
      int i = 3;
      std::cout << "i=" << i << " ::i=" << ::i << "\n";
   } 
}
The above prints i=3 ::i=1 rather than i=3 ::i=2. The intermediate variable is inaccessible inside the inner block.

The C++ scope resolution operator (optional_namespace_name::variable_name) refers to the global variable named variable_name in the specified namespace. If the namespace is omitted, it refers to the global variable named variable_name in the global namespace. There is no way in C or in C++ to access a hidden local variable.

There's an easy way to solve the hidden variable problem: don't do it. The one exception might be constructors and setters for a class. Some people think the following is the epitome of good style:
Code:
class Foo {
private:
    int value;
public:
    Foo (int value) : value(value) {}
    void setValue(int value) { this->value = value; }
}
I'm not in that class of people that think the above is "good style." (In my humble opinion, it's anything but "good style.") A significant number people do think that way, however.Regarding the use of a local variable in a for loop (e.g, for (int i=0;i <100;i++) {...}), whoever told that that is "bad style" because of the local declaration is telling you something from a coding style that was born in and is best relegated to the previous millennium. The advice from the current millennium is that scoping your variables to the smallest scope possible is good style.
 
  • Like
Likes jim mcnamara
  • #24
So there is nothing like main::i=2 ?
 
  • #25
D H said:
That depends on the language. C and C++ are rather different languages, despite suggestions from management such as "We need to hire a C/C++ programmer!"

In C, the canonical form for a for loop is to use for (variable_name=initial; !final_condition; variable_name++)[ { ...} . Using ++variable_name in lieu of variable_name++ is a sign that the programmer may be doing something suspicious. It's exactly the opposite in C++. Using ++variable_name is the canonical form in C++; uing variable_name++ is a sign that something dubious might be happening.
I programmed in C for years and I've never heard this. It's not about canonical form or even personal preference, ++i and i++ literally mean different things and ++i is more efficient.
 
Last edited:
  • #26
newjerseyrunner said:
I programmed in C for years and I've never heard this. It's not about canonical form or even personal preference, ++i and i++ literally mean different things and ++i is more efficient.
++variable_name is not more efficient than variable_name++ with most compilers if the variable is of a primitive type and if the result isn't used. For example, the generated code for for (int i = 0; i < 42; i++) { do_something_with(i); } vs for (int i = 0; i < 42; ++i) { do_something_with(i); } will be identical with most compilers. The same goes with the byte code generated in Java. It's a difference that makes no difference in this case.Except it does make a difference in terms of readability. A typical C or Java programmer will look askew at someone who write for (int i = 0; i < 42; ++i) ... because the canonical form in those languages is to use post increment operator in such loops. In C++, the canonical form is to use pre-increment because of the potential large expense of making a copy of a non-primitive object.
 
  • Like
Likes .Scott and newjerseyrunner
  • #27
newjerseyrunner said:
Also, in a loop, you should use ++i instead of i++.
newjerseyrunner said:
It's not about canonical form or even personal preference, ++i and i++ literally mean different things and ++i is more efficient.
I agree wholeheartedly that they mean different things. As to efficiency, I have never noticed any difference.

Example of different results:

These snippets all do slightly different things!

while (destination++ = source++);
...
while (++destination= source++);
...
while (destination++ = ++source);
...
while (++destination= ++source);
...
 
  • #28
Svein said:
I agree wholeheartedly that they mean different things. As to efficiency, I have never noticed any difference.

Example of different results:

These snippets all do slightly different things!

while (destination++ = source++);
...
while (++destination= source++);
...
while (destination++ = ++source);
...
while (++destination= ++source);
...
You won't notice a difference with POD, and yeah, those while loops are all different (I assume you meant == instead of =, since none of those will actually compile :P)
 
  • #29
newjerseyrunner said:
You won't notice a difference with POD, and yeah, those while loops are all different (I assume you meant == instead of =, since none of those will actually compile :P)
Oh, yes they will! To make it slightly more difficult, I left out the declarations. Here they are:

char *destination, *source;

Hint: The first example does the same thing as strcpy(). The others do almost the same thing but with small errors.
 
  • #30
I've not tried, but some of them should and some of them should not. Here is the difference, these should compile.
Code:
while (++destination= source++);
while (++destination= ++source);
Here is why, you are first incrementing destination, then assigning it. This means that you have an actual variable to write to, because the address of (++destination) is the address of destination.

Code:
while (destination++ = source++);
while (destination++ = ++source);
Should not compile. What you are assigning to is the l-value and that's required to have an actual address. Here, (destination++) resolves to a temporary variable that has no scope and immediately vanishes, turn on -Wall on your compiler, and you should get an error. I'd frankly be a little surprised if you even needed the -Wall option.

strcpy is sort of like this, but with one very big difference. destination=source won't copy the character, it'l copy the pointer (*destination = *source) does a copy, notice that you must dereference the pointer and like I said destination++ has no pointer.
 
  • #31
newjerseyrunner said:
strcpy is sort of like this, but with one very big difference. destination=source won't copy the character, it'l copy the pointer (*destination = *source) does a copy, notice that you must dereference the pointer and like I said destination++ has no pointer.
I absolutely agree. My only excuse is that I was late to an appointment and a bug snuck in (never write code in a hurry). Here are the correct statements:

char *destination, *source;

while (*destination++ = *source++);
...
while (*++destination= *source++);
...
while (*destination++ = *++source);
...
while (*++destination= *++source);
...
 
  • Like
Likes newjerseyrunner
  • #32
I never understood this, does ++source jump 4 bytes since it is an address ?
 
  • #33
jk22 said:
I never understood this, does ++source jump 4 bytes since it is an address ?
"Pointer arithmetic is scaled by the type of object pointed to."
What this means is that you can't know what incrementing, decrementing, adding an integer to, subtracting an integer from, or subtracting two pointers will do, unless you know what type they are pointers to.

If source is declared as char * source;
then incrementing source evaluates to the address in memory of the next character.

If source is declared as int * source;
then incrementing source evaluates to the address in memory of the next int, which would typically be four bytes higher in memory.

If source is declared as double * source;
then incrementing source evaluates to the address in memory of the next double, which would typically be eight bytes higher in memory.
 
  • Like
Likes jk22
  • #34
jk22 said:
I never understood this, does ++source jump 4 bytes since it is an address ?
No. It depends on what the pointer points to. Thus:
C:
char *cptr;
cptr++; /* Increases the pointer by 1, since it points to (an array of) characters */

short *sptr;
sptr++; /* Increases the pointer by 2, since it points to (an array of) shorts (16 bit) */

long *lptr;
lptr++; /* Increases the pointer by 4, since it points to (an array of) longs (32 bit) */

struct complicated *comptr;
comptr++; /* Increases the pointer by [I]sizeof(struct complicated[/I]), since it points to (an array of) structs */

But beware:

void *ptr;
ptr++;  /* Illegal, causes a compiler error. A void pointer is just a pointer, it cannot be used for anything but as a parameter in a call */

long *lptr;
lptr = ptr; /* Legal, since the void pointer is compatible with all pointers */
lptr++;  /* Now we know how to increment the pointer */
 
Last edited:
  • Like
Likes jk22

1. Why are local loops not being used more frequently in scientific research?

Local loops, or experiments conducted on a small scale, are often not used in scientific research because they may not accurately reflect real-world conditions. This can lead to unreliable results and hinder the progress of scientific knowledge.

2. Are there any advantages to using local loops in research?

Yes, there are some advantages to using local loops in research. They can be less expensive and easier to set up compared to large-scale experiments. They can also provide preliminary data that can inform larger experiments.

3. What are some potential drawbacks of relying on local loops for research?

One potential drawback of using local loops is that they may not be representative of larger, more complex systems. This can limit the generalizability of the results and make it difficult to apply them to real-world situations. Additionally, local loops may not be able to capture all the variables and interactions present in a larger system.

4. How do scientists determine whether to use local loops or larger experiments in their research?

The decision to use local loops or larger experiments depends on the research question and the goals of the study. If the goal is to understand how a system works in its entirety, a larger experiment may be more appropriate. However, if the goal is to test a specific hypothesis or gather preliminary data, a local loop may be more suitable.

5. Can local loops be used in combination with larger experiments?

Yes, local loops can be used in combination with larger experiments. This can provide a more comprehensive understanding of a system by allowing researchers to test specific variables in a controlled environment before conducting larger experiments. It can also help validate the results of larger experiments by providing additional data points.

Similar threads

  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
8
Views
1K
  • Programming and Computer Science
Replies
16
Views
1K
  • Programming and Computer Science
Replies
1
Views
875
  • Programming and Computer Science
2
Replies
66
Views
4K
  • Programming and Computer Science
Replies
2
Views
1K
  • Programming and Computer Science
Replies
7
Views
471
  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
6
Views
976
Back
Top