Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

goto label inside of if statement

208 views
Skip to first unread message

W Karas

unread,
Jan 23, 2014, 2:32:13 PM1/23/14
to
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();
}
}

Victor Bazarov

unread,
Jan 23, 2014, 2:55:35 PM1/23/14
to
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

W Karas

unread,
Jan 23, 2014, 3:08:19 PM1/23/14
to
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

Drew Lawson

unread,
Jan 23, 2014, 3:08:23 PM1/23/14
to
In article <ad5b0a02-29ab-4222...@googlegroups.com>
W Karas <wka...@yahoo.com> writes:
>
>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 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.

--
Drew Lawson What would Brian Boitano do?

Robert Wessel

unread,
Jan 23, 2014, 3:38:13 PM1/23/14
to
It arguably should be a error to jump to a different leg in the block
hierarchy, or into a more inner block, but just jumping "out" a layer
or N would just be normal practice (for example, breaking out of a
couple layers of loop).


IOW:

{
{
a:
{
b:
{
c:
{
d:
}
goto X;
e:
}
f:
{

b:, c:, e: and f: would be valid targets, but a: and d: not.




}

OTOH, C doesn't make any of those restrictions.

Elcaro Nosille

unread,
Jan 23, 2014, 3:45:44 PM1/23/14
to
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.

W Karas

unread,
Jan 23, 2014, 4:09:38 PM1/23/14
to
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 a variable 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 types and 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

unread,
Jan 23, 2014, 4:11:19 PM1/23/14
to
I added the -pendantic switch, still no warnings.

Mr Flibble

unread,
Jan 23, 2014, 5:56:34 PM1/23/14
to
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

W Karas

unread,
Jan 23, 2014, 6:54:38 PM1/23/14
to
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?

Mr Flibble

unread,
Jan 23, 2014, 7:08:07 PM1/23/14
to
It is awful because breaking out of a bock that's not the body of a
switch or loop is awful.

/Flibble

Mr Flibble

unread,
Jan 23, 2014, 7:09:22 PM1/23/14
to
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

Victor Bazarov

unread,
Jan 23, 2014, 10:16:51 PM1/23/14
to
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...

David Brown

unread,
Jan 24, 2014, 3:00:02 AM1/24/14
to
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.


Stuart

unread,
Jan 24, 2014, 4:04:32 AM1/24/14
to
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

Larry Evans

unread,
Jan 24, 2014, 3:30:35 PM1/24/14
to
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

unread,
Jan 24, 2014, 4:52:33 PM1/24/14
to
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

Stuart

unread,
Jan 25, 2014, 3:55:44 AM1/25/14
to
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

Alf P. Steinbach

unread,
Jan 25, 2014, 5:38:57 AM1/25/14
to
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;
}
[/code]


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;
}
[/code]


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

Jax

unread,
Jan 25, 2014, 10:15:23 AM1/25/14
to
Mr Flibble <flibbleREMOVE...@i42.co.uk> wrote in news:0s-
dnV4ZKKKpMnzPn...@giganews.com:
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 :)

Mr Flibble

unread,
Jan 25, 2014, 2:17:54 PM1/25/14
to
On 25/01/2014 08:55, Stuart wrote:
> 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.

Utter bullshit mate. Propagating error codes down a call stack and
checking error codes with if statements is far more difficult to grok
than exceptions.

Invalid parameters is a classic example of a 'std::domain_error' type of
exception.

Like it or not you are already using exceptions as 'new' can throw a
'std::bad_alloc' exception.

/Flibble

Tobias Müller

unread,
Jan 25, 2014, 5:59:28 PM1/25/14
to
Mr Flibble <flibbleREMOVE...@i42.co.uk> wrote:
> Like it or not you are already using exceptions as 'new' can throw a
> 'std::bad_alloc' exception.

Except 'new (nothrow)'.

Tobi

Mr Flibble

unread,
Jan 25, 2014, 7:36:32 PM1/25/14
to
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

Tobias Müller

unread,
Jan 26, 2014, 4:51:45 AM1/26/14
to
That's what propagation of error codes/error values means. It's tedious but
certainly possible.

Tobi

Mr Flibble

unread,
Jan 26, 2014, 11:03:40 AM1/26/14
to
On 26/01/2014 09:51, Tobias Müller wrote:
> Mr Flibble <flibbleREMOVE...@i42.co.uk> wrote:
>> On 25/01/2014 22:59, Tobias Müller wrote:
>>> Mr Flibble <flibbleREMOVE...@i42.co.uk> 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.

It is also possible for a person to be insane.

/Flibble

Jax

unread,
Jan 26, 2014, 2:13:22 PM1/26/14
to
Mr Flibble <flibbleREMOVE...@i42.co.uk> wrote in
news:3dqdne8xsb8OxXnP...@giganews.com:
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 :)

Mr Flibble

unread,
Jan 26, 2014, 3:11:25 PM1/26/14
to
'goto' should only be used to break out of nested loops.

/Flibble

Öö Tiib

unread,
Jan 26, 2014, 3:27:11 PM1/26/14
to
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.

Paavo Helde

unread,
Jan 26, 2014, 4:22:16 PM1/26/14
to
Jax <remove.bea...@gmail.com> wrote in
news:XnsA2C1C3...@127.0.0.1:


> 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?

As with all features, one uses goto if it is better than the alternatives.
And "better" here means primarily more readable and maintainable code.
Breaking out of deep nested loops with goto to near the beginning or the
end of a function is IMO okay, as the relevant state of the program after
the jump is pretty clear in such cases.

The same functionality can be always achieved with reorganizing the code,
possibly splitting it into multiple functions. Whether this makes the code
more readable and maintainable than 'goto' depends on the circumstances and
also on the taste (of the future readers and maintainers in particular). So
there is no clear-cut answer. One thing is clear, the need for 'goto' is
rare, if you find yourself writing a goto every week then something is
probably wrong.

HTH
Paavo

Gareth Owen

unread,
Jan 26, 2014, 4:32:59 PM1/26/14
to
Jax,

Take Paavo's advice and memorise it.

You'll not find it a better argument more cogently stated.
If you remember nothing else, remember the first sentence.

Jorgen Grahn

unread,
Jan 26, 2014, 6:10:55 PM1/26/14
to
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 .

Jax

unread,
Jan 27, 2014, 9:50:03 AM1/27/14
to
Paavo Helde <myfir...@osa.pri.ee> wrote in
news:XnsA2C1EDBF771FBm...@216.196.109.131:
Paavo.... Gareth tells me that your advice is reliable. I have made a note of
it. Thank you!

--
Jax :)

W Karas

unread,
Jan 27, 2014, 2:21:09 PM1/27/14
to
I'm honored, but you are too kind.
This is a situation where Pascal's nested functions where could be very advantageous. The nested function has access to the containing function's scope, so it is equivalent to a named block where "return" is a break from any level of nesting. Perhaps nested function support should be added to C++ (and C) since the hidden overhead (hidden pointer to containing function's scope) is straight-forward.

I believe the Standard already has one precedent for recommending a standard practice, namely, reserve symbols starting with underscore ( _ ) for standard library header files. Maybe this is a case where another such recommendation is needed. Perhaps that labels should begin with EXIT_BLOCK_ if and only if they are used exclusively to do a break from with a nested block. That has advantages over my tricky macros.

Alf P. Steinbach

unread,
Jan 27, 2014, 3:30:11 PM1/27/14
to
* W Karas:
> This is a situation where Pascal's nested functions where could be very
> advantageous. The nested function has access to the containing function's
> scope, so it is equivalent to a named block where "return" is a break from
> any level of nesting. Perhaps nested function support should be added to
> C++ (and C) since the hidden overhead (hidden pointer to containing
> function's scope) is straight-forward.

The following is valid C++, as of C++11:


[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;
[&]() -> void
{
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;
}
}
prev_c = c;
}
}
}
}();
cout << endl;

cout << "Found " << n << " interesting numbers." << endl;
}
[/code]

Exactly how it implements references to local variables is up to the
compiler, but a smart compiler would use a pointer to the stack frame.
Unlike Pascal's nested function a C++ lambda can alternatively capture
by value.

I would however use a named function instead of an inline lambda.

W Karas

unread,
Jan 27, 2014, 4:03:45 PM1/27/14
to
If a hypothetical nested function in C++ were (implicitly or explicitly) inline, then assuming good optimization, any overhead issues would be moot.

>
>
>
> I would however use a named function instead of an inline lambda.

If the (named) function substituted for the block were declared inline, then the "problem" would be the need to make explicit the block's dependence on local variables in the parameter list. Good optimization would hopefully make object level overhead issues moot in this case too.

Alf P. Steinbach

unread,
Jan 27, 2014, 4:32:14 PM1/27/14
to
On 27.01.2014 22:03, W Karas wrote:
> On Monday, January 27, 2014 3:30:11 PM UTC-5, Alf P. Steinbach wrote:
>> * W Karas:
>>
>>> This is a situation where Pascal's nested functions where could be very
>>
>>> advantageous. The nested function has access to the containing function's
>>

Please fix the quoting before posting.

- Alf


W Karas

unread,
Jan 27, 2014, 6:50:52 PM1/27/14
to
> Please fix the quoting before posting.
>
>
>
> - Alf

I have not found an alternative to using the groups.google.com web portal for usenet. I don't have enough time to properly follow this group, much less correct the mess that Google makes when quoting the original post. Is it best to simply delete all or most of the original post one is responding to when using the Google portal?

red floyd

unread,
Jan 27, 2014, 7:48:00 PM1/27/14
to

Vir Campestris

unread,
Jan 28, 2014, 4:57:00 PM1/28/14
to
On 26/01/2014 21:32, Gareth Owen wrote:
> Take Paavo's advice and memorise it.
>
> You'll not find it a better argument more cogently stated.
> If you remember nothing else, remember the first sentence.

I'll second that - but add a bit of data.

I've been writing C since before some of my co-workers were born (yes,
it scares me too!) and I've only written ONE goto ever.

And that didn't make it to checkin...

They do have a place, but it's vanishingly rare. I think the place is
not in a C++ program.

Andy

Jax

unread,
Jan 28, 2014, 5:11:22 PM1/28/14
to
Vir Campestris <vir.cam...@invalid.invalid> wrote in
news:lqCdnaGIYKcwunXP...@brightview.co.uk:
Andy.... you make me pause for thought. If I understand the implication of
what you wrote, then it means I haven't learned my first *real* C++
command!

--
Jax

Vir Campestris

unread,
Jan 29, 2014, 4:29:21 PM1/29/14
to
On 28/01/2014 22:11, Jax wrote:
> Andy.... you make me pause for thought. If I understand the implication of
> what you wrote, then it means I haven't learned my first*real* C++
> command!

Make note of Victor's post earlier in the thread. He's much better at
C++ than I am.

Andy

Jax

unread,
Jan 30, 2014, 12:12:53 PM1/30/14
to
Vir Campestris <vir.cam...@invalid.invalid> wrote in
news:oJSdnc0M0ewv73TP...@brightview.co.uk:
Wilco!

--
Jax :)
0 new messages