20

Disclaimer: I know it is obscure, and I would not program like that. I am aware of the preferred do-while statement, rather than that, the question is more about validity of a specific language construct.


Is goto always supposed to omit conditional expression of the for loop? From what I observed it skips both the first (i.e. initializing) and second expressions. Will this always happen this way or is this behavior purely compiler dependent?

#include <stdio.h>

int main(void)
{
    int m = 5;

    goto BODY;
    for (m = 0; m < 5; m++)
        BODY: puts("Message"); // prints "Message" once

    printf("m = %d\n", m); // prints m = 6

    return 0;
}
Mat
  • 202,337
  • 40
  • 393
  • 406
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • 5
    *"it skips both first (i.e. initializing) and second expression"*. Yup. *"the question is more about validity of a language construct"* The language construct is invalid for all sensible programmers, because there are much better ways to do the same thing (and don't require approval by language lawyers). – user3386109 Jun 03 '16 at 17:14
  • 6
    @user3386109: Sensible or not, there are also people who write C/C++ compilers and no matter how it looks, the `goto` is still part of the language. – Grzegorz Szpetkowski Jun 03 '16 at 17:19
  • I don't know it for a fact, but I suspect that `goto` into the body of a loop (if the compiler permits it at all) results in "undefined behavior". – Hot Licks Jun 03 '16 at 21:53
  • 4
    @user3386109 There is no such thing as "invalid for all sensible programmers". A language construct is either valid or invalid according to the language standard. In this case, the behaviour of the program is well-defined, because the construct is valid. – user253751 Jun 04 '16 at 09:39
  • 1
    @HotLicks: According to the C90 Rationale document [3.6.2](https://www.lysator.liu.se/c/rat/c6.html#3-6-2), It was considered to disallow that practice, but finally they left it as is, so to not break existing code. – Grzegorz Szpetkowski Jun 04 '16 at 10:41
  • 1
    On a somewhat related note, see [Duff's Device](http://stackoverflow.com/questions/514118/how-does-duffs-device-work). It doesn't use `goto`, but it's still a bit surprising when you first see it, due to how it uses `switch` to jump into the middle of the `do..while` loop. – PM 2Ring Jun 04 '16 at 12:55

6 Answers6

21

Yes, you're jumping over both m = 0 and m < 5, and this is as it should be.

for (A; B; C)
    D;

is equivalent to

{
    A;
  loop:
    if (B)
    {
        D;
        C;
        goto loop;
    }
}

There is no way to transfer control to a point between A and B.

The semantics of your loop are exactly like this "pure goto" version:

int m = 5;
goto BODY;
m = 0;
loop:
if (m < 5) 
{
  BODY: puts("Message"); // prints "Message" once
   m++;
   goto loop;
}
printf("m = %d\n", m); // prints m = 6
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
6

Does goto is always supposed to omit conditional expression of the for loop?

Yes. A goto jump is always an unconditional jump and the execution will carry from the label from there.

From C11 draft, § 6.8.6.1 The goto statement:

A goto statement causes an unconditional jump to the statement prefixed by the named label in the enclosing function.

With the only exception being:

The identifier in a goto statement shall name a label located somewhere in the enclosing function. A goto statement shall not jump from outside the scope of an identifier having a variably modified type to inside the scope of that identifier.

P.P
  • 117,907
  • 20
  • 175
  • 238
4

The goto statement in your code is causing an unconditional jump to a statement inside a for loop.When that statement is executed,the flow of the program is supposed to be dependent on the conditional expression in the loop.So,yes initialization inside the loop is skipped.

2

You should use a do/while loop, for example if you have the following for loop:

for(A ; B ; C)
{
     D;
}

You should use the following do/while loop:

A;
do
{
     D;
     C;
}while(B);

which will force a first iteration.

EDIT

See the comment by chux: If D; contains continue, this way will not work, you will need another way

EDIT II

As the question was edited, this answer is no longer the direct answer to the question, but I won't remove it as it might helps someone...

mame98
  • 1,271
  • 12
  • 26
2

A goto statement in C programming provides an unconditional jump from the 'goto' to a labeled statement in the same function.

Note the unconditional term here.

so yes it is supposed to omit conditional expression of for loop.

mssirvi
  • 147
  • 3
  • 14
2

This is perfectly legal in c. There's nothing wrong in jumping into a for loop so long as you don't skip over any declarations or initialisations of automatic variables.

In you case, m is incremented once and the loop terminates due to the stopping condition being met.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483