goto label inside of if statement

Discussion in 'C++' started by W Karas, Jan 23, 2014.

  1. W Karas

    W Karas Guest

    I was surprised to find that this code:

    struct A { A(); ~A(); };

    void bar();

    void foo(bool f)
    {
    if (0)
    {
    LAB: ;
    }
    else
    {
    A a;

    if (f) goto LAB;

    bar();
    }
    }

    will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .

    The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:

    #define BLOCK(NAME) if (0) { NAME: ; } else
    #define EXITBLOCK(NAME) goto NAME;

    struct A { A(); ~A(); };

    void bar();

    void foo(bool f)
    {
    BLOCK(XYZ)
    {
    A a;

    if (f) EXITBLOCK(XYZ)

    bar();
    }
    }
    W Karas, Jan 23, 2014
    #1
    1. Advertising

  2. On 1/23/2014 2:32 PM, W Karas wrote:
    > I was surprised to find that this code:
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > if (0)
    > {
    > LAB: ;
    > }
    > else
    > {
    > A a;
    >
    > if (f) goto LAB;
    >
    > bar();
    > }
    > }
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .
    >
    > The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:
    >
    > #define BLOCK(NAME) if (0) { NAME: ; } else
    > #define EXITBLOCK(NAME) goto NAME;
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > BLOCK(XYZ)
    > {
    > A a;
    >
    > if (f) EXITBLOCK(XYZ)
    >
    > bar();
    > }
    > }
    >


    And it actually skips the 'else' part when jumping into the 'if'
    section, yes? And how well do optimizers handle it?

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jan 23, 2014
    #2
    1. Advertising

  3. W Karas

    W Karas Guest

    On Thursday, January 23, 2014 2:55:35 PM UTC-5, Victor Bazarov wrote:
    > On 1/23/2014 2:32 PM, W Karas wrote:
    >
    > > I was surprised to find that this code:

    >
    > >

    >
    > > struct A { A(); ~A(); };

    >
    > >

    >
    > > void bar();

    >
    > >

    >
    > > void foo(bool f)

    >
    > > {

    >
    > > if (0)

    >
    > > {

    >
    > > LAB: ;

    >
    > > }

    >
    > > else

    >
    > > {

    >
    > > A a;

    >
    > >

    >
    > > if (f) goto LAB;

    >
    > >

    >
    > > bar();

    >
    > > }

    >
    > > }

    >
    > >

    >
    > > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .

    >
    > >

    >
    > > The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:

    >
    > >

    >
    > > #define BLOCK(NAME) if (0) { NAME: ; } else

    >
    > > #define EXITBLOCK(NAME) goto NAME;

    >
    > >

    >
    > > struct A { A(); ~A(); };

    >
    > >

    >
    > > void bar();

    >
    > >

    >
    > > void foo(bool f)

    >
    > > {

    >
    > > BLOCK(XYZ)

    >
    > > {

    >
    > > A a;

    >
    > >

    >
    > > if (f) EXITBLOCK(XYZ)

    >
    > >

    >
    > > bar();

    >
    > > }

    >
    > > }

    >
    > >

    >
    >
    >
    > And it actually skips the 'else' part when jumping into the 'if'
    >
    > section, yes? And how well do optimizers handle it?


    It runs correctly, at least this trivial example does:

    #include <cstdio>

    struct A {
    A() { std::printf("A\n"); }
    ~A() { std::printf("~A\n"); }
    };

    void bar() { std::printf("BAR\n"); }

    void foo(bool f)
    {
    if (0)
    {
    LAB: ;
    }
    else
    {
    A a;

    if (f) goto LAB;

    bar();
    }
    }

    int main(void)
    {
    foo(true);

    std::printf("---\n");

    foo(false);

    return(0);
    }

    output:

    A
    ~A
    ---
    A
    BAR
    ~A

    Works with GCC -O3 option
    W Karas, Jan 23, 2014
    #3
  4. Drew Lawson wrote:

    > I can't give a cite, but I was always under the impression that
    > a goto thta crosses block boundaries (into or out of a block) is
    > undefined behaviour.


    It's not possible when you go to a label that is after the
    initialization of an object.
    Elcaro Nosille, Jan 23, 2014
    #4
  5. W Karas

    W Karas Guest

    On Thursday, January 23, 2014 3:45:44 PM UTC-5, Elcaro Nosille wrote:
    > Drew Lawson wrote:
    >
    >
    >
    > > I can't give a cite, but I was always under the impression that

    >
    > > a goto thta crosses block boundaries (into or out of a block) is

    >
    > > undefined behaviour.

    >
    >
    >
    > It's not possible when you go to a label that is after the
    >
    > initialization of an object.


    That seems an accurate summary of what the Standard says, from 6.7-3:

    It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps(*) from a point where avariable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding typesand is declared without an initializer (8.5). [ Example:
    void f() {
    // ...
    goto lx; // ill-formed: jump into scope of a
    ly:
    X a = 1;
    // ...
    lx:
    goto ly; // OK, jump implies destructor
    // call for a followed by construction
    // again immediately following label ly
    }

    * The transfer from the condition of a switch statement to a case label is considered a jump in this respect.

    (This is a quote from the draft Standard dated 2013-10-13.)
    W Karas, Jan 23, 2014
    #5
  6. W Karas

    W Karas Guest

    On Thursday, January 23, 2014 2:32:13 PM UTC-5, W Karas wrote:
    > I was surprised to find that this code:
    >
    >
    >
    > struct A { A(); ~A(); };
    >
    >
    >
    > void bar();
    >
    >
    >
    > void foo(bool f)
    >
    > {
    >
    > if (0)
    >
    > {
    >
    > LAB: ;
    >
    > }
    >
    > else
    >
    > {
    >
    > A a;
    >
    >
    >
    > if (f) goto LAB;
    >
    >
    >
    > bar();
    >
    > }
    >
    > }
    >
    >
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .
    >
    >
    >
    > The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:
    >
    >
    >
    > #define BLOCK(NAME) if (0) { NAME: ; } else
    >
    > #define EXITBLOCK(NAME) goto NAME;
    >
    >
    >
    > struct A { A(); ~A(); };
    >
    >
    >
    > void bar();
    >
    >
    >
    > void foo(bool f)
    >
    > {
    >
    > BLOCK(XYZ)
    >
    > {
    >
    > A a;
    >
    >
    >
    > if (f) EXITBLOCK(XYZ)
    >
    >
    >
    > bar();
    >
    > }
    >
    > }


    I added the -pendantic switch, still no warnings.
    W Karas, Jan 23, 2014
    #6
  7. W Karas

    W Karas Guest

    On Thursday, January 23, 2014 5:56:34 PM UTC-5, Mr Flibble wrote:
    > On 23/01/2014 19:32, W Karas wrote:
    >
    >
    >
    > > #define BLOCK(NAME) if (0) { NAME: ; } else

    >
    > > #define EXITBLOCK(NAME) goto NAME;

    >
    > >

    >
    > > struct A { A(); ~A(); };

    >
    > >

    >
    > > void bar();

    >
    > >

    >
    > > void foo(bool f)

    >
    > > {

    >
    > > BLOCK(XYZ)

    >
    > > {

    >
    > > A a;

    >
    > >

    >
    > > if (f) EXITBLOCK(XYZ)

    >
    > >

    >
    > > bar();

    >
    > > }

    >
    > > }

    >
    >
    >
    > That code is awful mate, don't do it.
    >
    >
    >
    > /Flibble


    What't the better alternative when you have to break out of an outer block, or a block that's not the body of a switch or loop?
    W Karas, Jan 23, 2014
    #7
  8. On 1/23/2014 6:54 PM, W Karas wrote:
    >[..]
    > What't the better alternative when you have to break out of an outer

    block, or a block that's not the body of a switch or loop?

    Throw an exception.

    Breaking out of nested loops is the only situation in which it's
    reasonable, I think. The easiest thing in that case, however, is to
    wrap your loops in a function and 'return' from it. I know, I know, not
    the best solution, either, especially considering that you'd need the
    context pass in somehow. Perhaps wrap it in a lambda that captures
    everything...

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jan 24, 2014
    #8
  9. W Karas

    David Brown Guest

    On 23/01/14 20:32, W Karas wrote:
    > I was surprised to find that this code:
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > if (0)
    > {
    > LAB: ;
    > }
    > else
    > {
    > A a;
    >
    > if (f) goto LAB;
    >
    > bar();
    > }
    > }
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .
    >
    > The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:
    >
    > #define BLOCK(NAME) if (0) { NAME: ; } else
    > #define EXITBLOCK(NAME) goto NAME;
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > BLOCK(XYZ)
    > {
    > A a;
    >
    > if (f) EXITBLOCK(XYZ)
    >
    > bar();
    > }
    > }
    >



    Such unstructured mixes of control flow /are/ possible in C, and can
    sometimes be a good idea. But you need to be /very/ careful about what
    you are doing - usually it is not worth the cost in terms of the
    confusion you cause yourself and other readers. It is often better to
    just duplicate some code sections (either copy-and-paste duplication, or
    extracting a function which you might then make "static inline"). If it
    is possible to combine the sections safely, then let the compiler's
    optimiser do it for you.

    You might be interested in looking up "protothreads" for a way of mixing
    switches, labels, and other structures in order to make a simple
    cooperative multi-threading system. I haven't used it myself, but I
    believe it is all legal in C.
    David Brown, Jan 24, 2014
    #9
  10. W Karas

    Stuart Guest

    On 04/23/14, W Karas wrote:
    > I was surprised to find that this code:
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > if (0)
    > {
    > LAB: ;
    > }
    > else
    > {
    > A a;
    >
    > if (f) goto LAB;
    >
    > bar();
    > }
    > }
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .


    [snip]

    I remember that I read a lot of discussions about whether
    http://en.wikipedia.org/wiki/Duff's_device is legal C++ or undefined
    behaviour. Even though this is a bit different from your case, maybe
    those discussion contain some valuable information for you, too.

    Regards,
    Stuart
    Stuart, Jan 24, 2014
    #10
  11. W Karas

    Larry Evans Guest

    On 01/23/14 13:32, W Karas wrote:
    > I was surprised to find that this code:
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > if (0)
    > {
    > LAB: ;
    > }
    > else
    > {
    > A a;
    >
    > if (f) goto LAB;
    >
    > bar();
    > }
    > }
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra .
    >
    > The point, in case you were wondering, would be a macro-based "named block" pseudo-construct, where the block could be exited from any depth of block nesting, for example:
    >
    > #define BLOCK(NAME) if (0) { NAME: ; } else
    > #define EXITBLOCK(NAME) goto NAME;
    >

    The exit("loop label") statment here:

    http://openeuphoria.org/docs/lang_flow.html#_163_exitstatement

    sounds similar.

    -Larry
    Larry Evans, Jan 24, 2014
    #11
  12. W Karas

    Larry Evans Guest

    On 01/24/14 14:30, Larry Evans wrote:
    > On 01/23/14 13:32, W Karas wrote:
    >> I was surprised to find that this code:
    >>
    >> struct A { A(); ~A(); };
    >>
    >> void bar();
    >>
    >> void foo(bool f)
    >> {
    >> if (0)
    >> {
    >> LAB: ;
    >> }
    >> else
    >> {
    >> A a;
    >>
    >> if (f) goto LAB;
    >>
    >> bar();
    >> }
    >> }
    >>
    >> will compile without warnings using GCC 4.7.3, even with -Wall and
    >> -Wextra .
    >>
    >> The point, in case you were wondering, would be a macro-based "named
    >> block" pseudo-construct, where the block could be exited from any
    >> depth of block nesting, for example:
    >>
    >> #define BLOCK(NAME) if (0) { NAME: ; } else
    >> #define EXITBLOCK(NAME) goto NAME;
    >>

    > The exit("loop label") statment here:
    >
    > http://openeuphoria.org/docs/lang_flow.html#_163_exitstatement
    >
    > sounds similar.
    >
    > -Larry
    >
    >

    Also:

    http://goanna.cs.rmit.edu.au/~dale/ada/aln/5_control_structures.html#RTFToC10

    However, the main differences is that the exit's are used to exit loops,
    not to jump into a branch of an if statement.

    -regards,
    Larry
    Larry Evans, Jan 24, 2014
    #12
  13. W Karas

    Stuart Guest

    On 1/23/2014, W Karas wrote:
    >> What't the better alternative when you have to break out of an outer
    >> block, or a block that's not the body of a switch or loop?


    on 01/24/14, Victor Bazarov wrote:
    > Throw an exception.


    -1

    Using an exception for "normal" control flow is IMHO a bad design
    choice. My wife had to struggle with a real ugly piece of code for over
    two weeks where an exception was used to indicate that some algorithm
    had to be invoked with different parameters. Really yuk.

    I have to admit that using exceptions is tempting, but it makes the
    intended control flow harder to "read": If you see the code that throws
    the exception it is harder for you to figure out what will be the next
    statement because the exception might propagate through multiple levels
    on the stack. A plain old return-statement tells you exactly what the
    next statement will be.

    > Breaking out of nested loops is the only situation in which it's
    > reasonable, I think. The easiest thing in that case, however, is to
    > wrap your loops in a function and 'return' from it.


    +1

    This is the technique I prefer, even though premature returns are often
    labeled as "GOTO in disguise" by some people (for example my
    co-workers). You have to pay the price of having to re-structure your
    code so that individual loops have their own function.

    > I know, I know, not
    > the best solution, either, especially considering that you'd need the
    > context pass in somehow. Perhaps wrap it in a lambda that captures
    > everything...


    Parameter passing should not be such an issue if you make your function
    an object. Then you can simply put the parameters that are needed only
    in the inner-most loops into a member variable, so there is no need to
    "pass through" them from one function to the next.

    This is usually not too much of an overkill because algorithms that tend
    to need GOTOs are usually more time-consuming beasts, where you want to
    be able to give the caller some kind of progress information or some
    means to pause/stop the computation, so you will most probably wrap the
    algorithm in an object, anyway.

    Regards,
    Stuart
    Stuart, Jan 25, 2014
    #13
  14. On 23.01.2014 20:32, W Karas wrote:
    > I was surprised to find that this code:
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > if (0)
    > {
    > LAB: ;
    > }
    > else
    > {
    > A a;
    >
    > if (f) goto LAB;
    >
    > bar();
    > }
    > }
    >
    > will compile without warnings using GCC 4.7.3, even with -Wall and -Wextra.


    It's okay to jump across block boundaries with "goto", either into or
    out of a block, and it's also okay to jump into block boundaries with a
    `switch` (the old "duff's device" relied on that), but you can't

    * jump across function boundaries or

    * skip the initialization of a variable


    > The point, in case you were wondering, would be a macro-based "named block"
    > pseudo-construct, where the block could be exited from any depth of block
    > nesting, for example:
    >
    > #define BLOCK(NAME) if (0) { NAME: ; } else
    > #define EXITBLOCK(NAME) goto NAME;
    >
    > struct A { A(); ~A(); };
    >
    > void bar();
    >
    > void foo(bool f)
    > {
    > BLOCK(XYZ)
    > {
    > A a;
    >
    > if (f) EXITBLOCK(XYZ)
    >
    > bar();
    > }
    > }


    That's ingenious.

    But, heads-up: there once was a version of a Unix shell written in C
    with macros and support functions defined to make it look like Pascal.
    Heavy emphasis on **was**.

    And for example, when I once defined a WITH macro (corresponding to C#
    "using"), and even enlisted help from the community with the quality
    assurance of that, I thought this was the next best thing since pizza
    slices. It used a similar trick internally, using an `if` to introduce a
    variable for the `else` part. I have not used that macro since.

    * * *

    So, how to reasonably exit from a nested scope, without such shenanigans?

    Let's consider the common example, a nested loop, with some nested
    conditionals thrown in for good measure, plus an "at the end" action:


    Code:
    #include <iostream>
    #include <math.h>       // sqrt
    using namespace std;
    
    auto main()
    -> int
    {
    int const max_a         = 12345;
    int const max_numbers   = 42;
    int n = 0;
    int prev_c  = 0;
    for( int a = 1; a <= max_a; ++a )
    {
    for( int b = 1; b < a; ++b )
    {
    int const c_sq = a*a + b*b;
    int const c = int( sqrt( c_sq ) + 0.5 );
    if( c*c == c_sq )
    {
    if( c < prev_c )
    {
    cout << (n > 0? " " : "") << c;
    ++n;
    if( n == max_numbers )
    {
    goto finished;
    }
    }
    prev_c = c;
    }
    }
    }
    finished:
    cout << endl;
    
    cout << "Found " << n << " interesting numbers." << endl;
    }
    

    The C++ construct that is a scope that can be exited from some nested
    scope, is a function, and in most all cases introducing (refactoring as)
    a function is a good solution.

    In C++03 that function must be a named function or a function template
    instantiation. As a named function it can be at namespace scope or a
    member of a local class. In C++11 it can also be an anonymous function,
    as a lambda.

    The code below shows a C++03-style named function refactoring:


    Code:
    #include <iostream>
    #include <math.h>       // sqrt
    using namespace std;
    
    auto list_interesting_numbers(
    int const   max_numbers,
    int const   max_a         = 12345
    )
    -> int
    {
    int n = 0;
    int prev_c  = 0;
    for( int a = 1; a <= max_a; ++a )
    {
    for( int b = 1; b < a; ++b )
    {
    int const c_sq = a*a + b*b;
    int const c = int( sqrt( c_sq ) + 0.5 );
    if( c*c == c_sq )
    {
    if( c < prev_c )
    {
    cout << (n > 0? " " : "") << c;
    ++n;
    if( n == max_numbers )
    {
    return n;
    }
    }
    prev_c = c;
    }
    }
    }
    return n;
    }
    
    auto main()
    -> int
    {
    int const n = list_interesting_numbers( 42 );
    cout << endl;
    
    cout << "Found " << n << " interesting numbers." << endl;
    }
    

    Since the `goto` has been eliminated, the effect of any statement here
    is clear just from inspecting the statement itself.

    Also, the function is more reusable.

    For some special cases of nested loops there are some other clean
    alternatives. For example, looping over a rectangular set of positions
    can be done with a single logical position variable. But I do not think
    that the Pascal solution, of introducing extra boolean "are we finished
    yet" variables, checked at every loop iteration, is clean for C++. That
    solution was nice for Pascal, and also for C, where a single exit point
    (SESE) is important. However, in C++ a single exit point can almost
    never be relied on (so that code that does, is misguided), and one has
    tools to deal with multiple exit points, namely destructors and `catch`.


    Cheers & hth.,

    - Alf
    Alf P. Steinbach, Jan 25, 2014
    #14
  15. W Karas

    Jax Guest

    Mr Flibble <> wrote in news:0s-
    :

    > On 24/01/2014 00:08, Mr Flibble wrote:
    >> On 23/01/2014 23:54, W Karas wrote:
    >>> On Thursday, January 23, 2014 5:56:34 PM UTC-5, Mr Flibble wrote:
    >>>> On 23/01/2014 19:32, W Karas wrote:
    >>>>
    >>>>
    >>>>
    >>>>> #define BLOCK(NAME) if (0) { NAME: ; } else
    >>>>
    >>>>> #define EXITBLOCK(NAME) goto NAME;
    >>>>
    >>>>>
    >>>>
    >>>>> struct A { A(); ~A(); };
    >>>>
    >>>>>
    >>>>
    >>>>> void bar();
    >>>>
    >>>>>
    >>>>
    >>>>> void foo(bool f)
    >>>>
    >>>>> {
    >>>>
    >>>>> BLOCK(XYZ)
    >>>>
    >>>>> {
    >>>>
    >>>>> A a;
    >>>>
    >>>>>
    >>>>
    >>>>> if (f) EXITBLOCK(XYZ)
    >>>>
    >>>>>
    >>>>
    >>>>> bar();
    >>>>
    >>>>> }
    >>>>
    >>>>> }
    >>>>
    >>>>
    >>>>
    >>>> That code is awful mate, don't do it.
    >>>>
    >>>>
    >>>>
    >>>> /Flibble
    >>>
    >>> What't the better alternative when you have to break out of an outer
    >>> block, or a block that's not the body of a switch or loop?

    >>
    >> It is awful because breaking out of a bock that's not the body of a
    >> switch or loop is awful.

    >
    > Hiding goto inside a macro does not make goto any less bad. The only
    > acceptable use of goto is to break out of a deeply nested loop.
    >
    > /Flibble


    I'm starting to learn C++ and the first example of GOTO I saw went round
    and round in an endless loop. That's not very good!

    --
    Jax :)
    Jax, Jan 25, 2014
    #15
  16. Mr Flibble <> wrote:
    > Like it or not you are already using exceptions as 'new' can throw a
    > 'std::bad_alloc' exception.


    Except 'new (nothrow)'.

    Tobi
    Tobias Müller, Jan 25, 2014
    #16
  17. Mr Flibble <> wrote:
    > On 25/01/2014 22:59, Tobias Müller wrote:
    >> Mr Flibble <> wrote:
    >>> Like it or not you are already using exceptions as 'new' can throw a
    >>> 'std::bad_alloc' exception.

    >>
    >> Except 'new (nothrow)'.

    >
    > Which means checking for null pointers with if statements all over your
    > code and trying to decide what to do all over your code.


    That's what propagation of error codes/error values means. It's tedious but
    certainly possible.

    Tobi
    Tobias Müller, Jan 26, 2014
    #17
  18. W Karas

    Jax Guest

    Mr Flibble <> wrote in
    news::

    > On 25/01/2014 22:59, Tobias Müller wrote:
    >> Mr Flibble <> wrote:
    >>> Like it or not you are already using exceptions as 'new' can throw a
    >>> 'std::bad_alloc' exception.

    >>
    >> Except 'new (nothrow)'.

    >
    > Which means checking for null pointers with if statements all over your
    > code and trying to decide what to do all over your code.
    >
    > /Flibble


    Flibble I am very new to C++ and would like to get your recommendation. Do
    you mean that GOTO shouldn't ever be used or is it okay in certain
    circumstances?

    --
    Jax :)
    Jax, Jan 26, 2014
    #18
  19. W Karas

    Öö Tiib Guest

    On Sunday, 26 January 2014 21:13:22 UTC+2, Jax wrote:
    > Do you mean that GOTO shouldn't ever be used or is it okay in certain
    > circumstances?


    One is certain that C++ programs can be written without using 'goto'
    because there are large C++ code-bases (millions of lines) without a
    single 'goto' in them.

    Goto may cause that program logic is hard to understand. However
    the silly tricks with loops, switches, continues or break's that I have
    seen sometimes written for emulating goto are even worse. So if you
    ever feel that you need to write tricky code to avoid goto then better
    use goto.
    Öö Tiib, Jan 26, 2014
    #19
  20. W Karas

    Jorgen Grahn Guest

    On Sun, 2014-01-26, Öö Tiib wrote:
    > On Sunday, 26 January 2014 21:13:22 UTC+2, Jax wrote:
    >> Do you mean that GOTO shouldn't ever be used or is it okay in certain
    >> circumstances?

    ....
    > So if you ever feel that you need to write tricky code to
    > avoid goto then better use goto.


    Agreed, but keeping in mind that:
    - there are always (more or less) cleaner solutions, if you have
    the time and guts to refactor the code a bit (and sometimes you
    don't)
    - goto is less useful in C++ than in C, since RAII can replace those
    "goto cleanup1", "goto cleanup2" ... constructs.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Jan 26, 2014
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. youngsun park
    Replies:
    2
    Views:
    625
    David Pursley
    Nov 18, 2003
  2. Skybuck Flying

    VHDL Goto statement ?

    Skybuck Flying, Aug 8, 2005, in forum: VHDL
    Replies:
    9
    Views:
    6,119
    ajahn
    Aug 26, 2005
  3. Replies:
    10
    Views:
    713
  4. Knut Krueger
    Replies:
    8
    Views:
    263
    Knut Krueger
    Aug 20, 2013
  5. Jax
    Replies:
    1
    Views:
    102
Loading...

Share This Page