for (;;) { }
What does that piece of code do in C?
Well I am familiar with something like for (i=0; i<100; i++) { }
but I haven't understood what happens if you leave the parts between the semi-colons blank. I would have thought if just ran the code between the braces once, but then why bother with the for ( ; ; )?
Incidentally, is it considered bad practice to modify the index variable inside the loop?
Well I am familiar with something like for (i=0; i<100; i++) { }
but I haven't understood what happens if you leave the parts between the semi-colons blank. I would have thought if just ran the code between the braces once, but then why bother with the for ( ; ; )?
Incidentally, is it considered bad practice to modify the index variable inside the loop?
Post edited by wilsonsamm on
Comments
If you leave out the condition check (as above), the loop will never exit unless the code executing within the loop somehow forces a break from the loop.
Bytes:Chuntey - Spectrum tech blog.
And you are right. I examined the code and there was a break; there.
ah, in the past I have written while (1), and some compilers have generated code to check if 1 is non-zero. a handy optimisation for people with such compilers!
Yes.
Yeah, the for infinite loop is generally considered a better alternative to the while infinite loop because some compilers generate a conditional check for the latter. I'm not sure if this is a hangover from the previous c coding days though because you would expect compilers to have become smarter now.. ;)
Bytes:Chuntey - Spectrum tech blog.
for (Initialise ; Condition ; Update Value)
Initialise
This statement is used to initialise a variable for example: x = 1. It can also be used to declare and initialise a variable as in: int x = 1;
Declare means: Reserve a named space in memory for data of the specified type, i.e. create a variable.
Initialise means: Give the variable its first value.
Condition
This consists of a boolean expression such as: x <= 10. The loop will continue whilst the condition evaluates to true. The condition is evaluated once per loop, not contunually within the loops structure.
Update Value
This updates a variable for example : x = x + 1 (x++ for short). Typically you are going to want to uptate the a control variable which was Initialised in the For loops paramiter list.
//Loop from 10 down to 1 (does somthing 10 times) for (x = 10; x > 0 ; x= x - 1) { ///Do somthing }However, each of the Initialise, Condition, Update Value expressions are optional, so you can have only some or none if you want. For example
int x; int amt [B]for (;;;)[/B] { cout << "How quonkers are you filling the dispenser with?"; cin >> x; [B]for ( ; x < 10; x = x -1) [/B] { cout << "How many quonkers would you like"; cin >> amt; if (x - amt >= 0) x = x - amt; else cout << "Sorry not enough quonkers left"; }//end for cout << " Sorry no more quonkers left please refill machine"; }//end forfor (x=10 ; ; ) { if (doyourthing()) then break; }and it would doyourthing until that returned true, and x would remain at ten (unless doyourthing changed it) but what's the scope of that variable? Is this following code possible?
int x for ( ; (x>7 && x<16) ; ) { printf("give me a value between 7 and 16 exclusive"); scanf("%d", x); }Yes you could do your first example.
In your first example x was declaired in the for loop; therefore, its scope is within the brackets of the for loop.
However, in your second example the scope of x is not limited to the loop, but the whole method the code woud reside in, following its declaration.
Not to be too pedantic but in fact he has not declared x in the for loop. To declare: for (int x = 10; ; ). This would cause x to be local to the scope of the loop.
Bytes:Chuntey - Spectrum tech blog.
Which is pretty what I was saying. The only correction need is that x is not declaired in the loop but the for loops paramiter list.
And what if there was already an x in the function where the loop was? then that x would not be accessible inside the for loop.
No, the local variable will hide the global one.
Don't mean to put you off but wouldn't it be faster and easier for you to refer to a book or online tutorial than posting on the forum back and forth?
Bytes:Chuntey - Spectrum tech blog.
True.
I have a small 1992 book called "C simply". It explains some of the stuff but I'm learning new things by asking here...
Global being the variable which was declared ouside of a method. However, I'm not sure thats what he was asking, I could be wrong though.
However inside a method if you had
main () { int x = 0; for (int x = 0; x < 10; x ++) { cout << x; } }Then you would get a variable already defined error just as you would in this situation
main () { for (int x = 0; x < 10; x ++) { cout << x; int x = 5; } }The use of cout implies C++. In which case neither variant will give a compile error. The first one will output the value of x declared in the for statement within the loop, hiding the x declared at the top of main, ie output the numbers 0 to 9. The second will output the value of x declared in the for statement too, as the cout line precedes the second declaration of x, so 0 to 9 again. If the second x was declared before the cout line, then it would output 5 ten times.
If we are talking about C, then declaring x in the for statement is illegal, unless you are using C99. C99 will behave as C++. Ye olde C won't compile.
Good shout, I've had all the C Javaised out of me. However, will not my second example result in 0 followed by an infinite number of 6s?
No it won't. At the cout line the only x in scope is the one declared in the for statement. The next line introduces a new x, which hides, but doesn't over-write the previous x. The new x then immediately drops out of scope when the loop loops. The original x in the for statement is still in scope, is incremented, tested against the exit condition, and cout prints the new value. That's what happens with gcc at any rate.
You know I'm going to test this later in Visual Studio. I'll also try some older stand alone C++ compiler.
It shouldn't. It shouldn't even compile because if it did there would be two versions of x declared in the same scope. VS doesn't compile it, which I believe is the correct behaviour.
You can get it to compile by modifying it to be:
for (int x = 0; x < 10; x ++) { { cout << x; int x = 5; } }Since the additional braces will create a new scope. Then it'll behave as you suggested.Here's the code tarted up a bit, and made unC++ified:
//wos.c #include <stdio.h> int main() { for (int x = 0; x < 10; x ++) { printf("%d\n", x); int x = 5; } return 0; }Both the following build without warnings or errors:
And both produce the same output: I don't know the standard well enough to know if the behaviour is correct, wrong, or undefined behaviour.
Edit
But a few minutes on Google finds the relevant part of the c99 standard:
So, the for loop above should transform to:
int x = 0; // expr-1 while(x < 10) // expr-2 { printf("%d\n", x); int x = 5; x++; // expr-3 }So VC is wrong, and gcc and clang are correct.As a random note, I always use the 'for ( ;; )' construct instead of the 'while(1)' one.
For some reason, it reads easier for me, as I immediately see "forever" in it. :-)
Nope. According to the C++ standard, section 6.4:
3 A name introduced by a declaration in a condition (either introduced by the type-specifier-seq or the declarator of the condition) is in scope from its point of declaration until the end of the substatements controlled by the condition. If the name is re-declared in the outer- most block of a substatement controlled by the condition, the declara- tion that re-declares the name is ill-formed. [Example: if (int x = f()) { int x; // ill-formed, redeclaration of 'x' } else { int x; // ill-formed, redeclaration of 'x' } --end example]And section 6.5 clarifies that this same ruling applies to iteration statements as well.
Can't say I'm overly surprised. GCC is (somewhat ironically) not nearly as standards compliant as VC++.
yellow cover with C in 3d with bricks as the filling
we had an excellent C teacher at uni (Tony Bermudez) he was supposed to have written a book..he gave us hand out notes of basically the book in a rough form..
it covered everything , headers etc . I should see if I have it someone, it was very well written
he's one of the few teachers I remember who were decent , and could actually teach... instead of teaching as a sideline to fund their phd etc
Yep. And as section 6.5.3 clarifies:
6.5.3 The for statement [stmt.for] 1 The for statement for ( for-init-statement; conditionopt ; expressionopt ) statement is equivalent to { for-init-statement while ( condition ) { statement expression ; } }Look at the code which the standard says is equivalent to the for statement. A variable declared in for-init-statement is not in the same scope as a variable declared in statement.So you can do
for ever
Serious note: Use ++x rather than x++ in a for loop (compiler will optimise it as same thing for built in types but when you go onto using c++ iterators you don't want to make a copy (which is what x++ has to do). Get into good habits early.
Do you mean that ++x; uses fewer instructions so that the resulting loop is tighter than had I chosen x++;?
That makes no sense... I don't know about x86, but the PDP-11 assembly has both INC Rn and DEC Rn (increment and decrement). The end of the loop could like like this:
loop: CLR R5 # set the index variable to zero. (we'll keep it in register 5) /* loop here... */ CMP R5++,R4 # increment R5 and test it against R4 BNE loop # branch if not equal (to zero, that is) to the beginning of the loopwhich means x++; the only difference as far as I can tell is that ++x; has to compile toMOV -01, R5 # we set it to -1 loop: INC R5 # increment /* the loop goes here */ CMP R5,R4 # when R5 becomes equal to R4 the loop will exit. BNE loopwhich is longer.The while (1) would compile to
while: TST 01 # test if 1 BEQ out # is equal to zero and if so, branch out. /* while loop */ JMP while out: /* rest of program goes here */which is shorter.That is, of course, unless I've missed something basic. It's quite early.
EDIT: of course I've missed something basic. It would be better to compare the index variable to an absolute value rather than keeping this value in the processor register just for comparison.
You're forgetting that in C++ x might not be as simple as an integer, it might be some massive multi-megabyte structure and that is when the difference hurts performance. Writing ++x rather than x++ even when it's not strictly important tries to teach you to avoid the possibility creeping in by accident.
Anyway, what copy is being made when you post-increment?
It's more likely to be an iterator and those are fairly lightweight.
What x++ does is
Copy x
Increment x
Return the copy made earlier
++x does this
Increment x
Return x
The compiler should optimise [the copy] out if the return value is not stored.
In C++ you can overload pre and post increment operators and if the return value is discarded ++x should be preferred to x++ because it is never less efficient and may be more efficient.
It's just a good habit to get into.
EDIT: Of course, for this reason C++ should be called ++C (since evaluating C++ returns C).