tags:

views:

130

answers:

4

C language allows jumping inside loop. What would be the use of doing so?

  if(n > 3) {

    i = 2;
    goto inner;
  }

   /* a lot of code */

   for(i = 0; i < limit ;i ++) {

    inner:
    /* ... */
   }
+2  A: 

It's certainly a questionable construct. A design that depends on this behavior is probably a poor design.

You've tagged this as C++, but C++ (intelligently, IMO) doesn't allow you to jump inside a loop where a variable was declared in the first part of the for statement:

int main()
{
    int q = 5;

    goto inner;

    for (int i = 0; i < 4; i++)
    {
        q *= 2;
inner:
        q++;
        std::cout << q << std::endl;
    }    
}

g++ output:

l.cpp: In function ‘int main()’:
l.cpp:12: error: jump to label ‘inner’
l.cpp:7: error:   from here
l.cpp:9: error:   crosses initialization of ‘int i’

Initializing i before the loop allows the program to compile fine (as would be expected).

Oddly, compiling this with gcc -std=c99 (and using printf instead) doesn't give an error, and on my computer, the output is:

6
13
27
55

as would be expected if i were initialized outside the loop. This might lead one to believe that int i = 0 might be simply "pulled out" of the loop initializer during compilation, but i is still out of scope if tried to use outside of the loop.

Mark Rushakoff
I believe C99 won't accept that either.
Nyan
I only get 6 as output! using gcc -std=c99 -pedantic-errors
Nyan
I find out that i value is garbage!
Nyan
@Nyan: That might imply that this is either undefined behavior (which I would expect to be caught in `-Wall`) or that it's a bug in gcc. I'm using GCC 4.2.1... Comeau online in strict C99 gives two warnings about skipping initialization of `i`. So, I'm not sure what the correct behavior is. Probably need to consult the standard.
Mark Rushakoff
@Mark Rushakoff: C99 allows jumping into the scope of the declaration - however doing so leaves the declared variable uninitialised. Reading an uninitialised variable is just as bad as it always was.
caf
@caf: Which section of the standard says that? Maybe I'm just overlooking it, but I didn't find it in my copy of the C99 draft.
Mark Rushakoff
@Mark Rushakoff: 6.8.6.1 puts the only restriction on the `goto` statement being that you can't jump into the scope of VLAs ("identifier having variably-modified type"). 6.8 says that initializers are evaluated and values are stored in the objects "each time the declaration is reached in the order of execution, as if it were a statement". So if you jump past an initializer, it is never "reached in the order of execution" and the variable is left with an indeterminate value.
caf
+1  A: 

If you've ever coded in Assembler (ASM), then you'll know that GOTOs are pretty standard, and required, actually. The C Language was designed to be very close to ASM without actually being ASM. As such, I imagine that "GOTO" was kept for this reason.

Though, I'll admit that GOTOs are generally a "bad idea, mmmkay?" in terms of program flow control in C and any other higher level language.

Pretzel
GOTOs fit into a general category that I call "Rules that you should ONLY break after you understand why it's a rule in the first place."
Brian Postow
I agree with you completely. That said, I have yet to find a case in C or any other high level language where I needed to use GOTO. The only time I ever recall using GOTO was in ASM and BASIC (and the latter was over 25 years ago.) :-)
Pretzel
A: 

From http://en.wikipedia.org/wiki/Duff%27s_device

In computer science, Duff's device is an optimized implementation of a serial copy that uses a technique widely applied in assembly language for loop unwinding.

...

Reason it works
The ability to legally jump into the middle of a loop in C.

Dinah
A: 

IOCCC

Brian Postow