News for hackers. Stuff that matters.
Re:The Evolution of C Programming Practices: A Study of Unix... by bio_end_io_t on Friday May 11, 2018 @08:12AM (#17046650)
It bothers me when "goto" is assumed to be "a maligned language construct".

People who think "goto" is evil should also give up the other jump statements: continue, break, and return (and also switch, though its not listed as a jump instruction in the C standard, at least not in '89 or '99).

You can see some contradictions in the paper regarding goto. For example, they state that deep nesting should be avoided, but goto should be avoided as well, even though one benefit of using goto is to limit nesting depth. From the Linux Kernel coding style doc: - unconditional statements are easier to understand and follow - nesting is reduced - errors by not updating individual exit points when making modifications are prevented - saves the compiler work to optimize redundant code away ;)

Re:The Evolution of C Programming Practices: A Study of Unix... by rmind on Friday May 11, 2018 @08:55AM (#17046936)
This is because certain coding standards are designed to be idiot-proof. Unfortunately, that can result in tasteless code and sometimes undesirable workarounds (e.g. using "goto" have one exit path for errors is a perfectly valid use).

When Dijkstra wrote his famous essay "Go To Statement Considered Harmful" (1968), it was a manifesto against unstructured programming i.e. the spaghetti code. However, the use of "goto" per se does not imply unstructured programming. Donald Knuth wrote a wonderful essay "Structured Programming with go to Statements" (1974) to make this point.

Availability of "goto" in C merely gives us more flexibility, but it does not mean that we should start writing unstructured code.

Re:The Evolution of C Programming Practices: A Study of Unix... by Isamu on Friday May 11, 2018 @10:49AM (#17047665)
Dijkstra was concerned about being able to reason about code, and spaghetti code can make it impossible to decompose. A single goto within a function is not a big deal, and that's not really what he was worried about.

Few people have worked on real spaghetti code, thousands of lines with no functions, no modules, just spectacular leaps forward, backwards, leaping forward into the middle of huge loops, leaping backwards into the middle of loops, giant loops nested with and partially overlapping other loops.

I worked on such code, trying to decompose it in order to organize it into subroutines. It resisted my efforts almost completely. Fortran IV I think.

Re:The Evolution of C Programming Practices: A Study of Unix... by samatman on Friday May 11, 2018 @11:40AM (#17048146)
Lua added goto just recently, and it's benign, because it can't escape its calling context.

Users were agitating for `continue` to join `break` for control flow interruption. Lua instead chose to provide all the non-structured control flows you would like as a primitive; scoping it lexically keeps it from breaking composition.

Re:The Evolution of C Programming Practices: A Study of Unix... by ufo on Friday May 11, 2018 @12:05PM (#17048426)
I still hope that we might be able to convince the Lua authors to add continue one day. It would be very convenient.

I think the real reason why it hasn't been added to the language yet is that it has a weird interaction with the way Lua scopes its repeat-until loops. The justification about having a single control-flow structure is more of an excuse.

Re:The Evolution of C Programming Practices: A Study of Unix... by samatman on Friday May 11, 2018 @05:42PM (#17050977)
As a contrasting opinion, I would like the break keyword to be formally defined as a sugar for a special labeled goto.

Since it's a keyword, you can't create your own ::break:: label, so that would be fine.

Re:The Evolution of C Programming Practices: A Study of Unix... by ufo on Saturday May 12, 2018 @11:54AM (#17054625)
I'd be OK with that. But let me type `break` and `continue`, with all the sugar that entails :)
Re:The Evolution of C Programming Practices: A Study of Unix... by loup-vaillant on Friday May 11, 2018 @05:32PM (#17050948)
> Few people have worked on real spaghetti code

The closest I've come was my own code: minsweeper on my Ti-82 graphical calculator. I Separated the program in various sections, then used `goto` to jump where I needed. I was tempted at some point to use the "call program" facility instead, but that would have meant exposing those programs to the end users, so I just lumped everything in one file.

Reminds me why I love functions.

Re:The Evolution of C Programming Practices: A Study of Unix... by tomcatfish on Sunday May 13, 2018 @01:12AM (#17057455)
Oh god, I feel for you. My first real language was when I had my TI-84, and you NEEDED goto if you didn't want to clutter up the user's machine with a bunch of things they should never-ever press. God, what horrible yet nostalgic memories.
Re:The Evolution of C Programming Practices: A Study of Unix... by pletnes on Friday May 11, 2018 @04:29PM (#17050594)
I’ve seen a few Fortran goto subroutines. I somehow get the feeling that the two following facts are mathematically related: some graphs cannot be drawn on a two-dimensional sheet of paper, and some subroutines cannot be decomposed into smaller subroutines.
Re:The Evolution of C Programming Practices: A Study of Unix... by masklinn on Friday May 11, 2018 @08:27AM (#17046757)
> People who think "goto" is evil should also give up the other jump statements: continue, break, and return (and also switch, though its not listed as a jump instruction in the C standard, at least not in '89 or '99).

That makes no sense. goto is maligned because it's unstructured, the other constructs you list are structured and restricted. Much like loops, conditionals and function calls they're specific and "tamed".

Not only that, but the historical movement against goto happened in a context were goto was not just unstructured but unrestricted (to local functions).

Even K&R warns that goto is "infinitely abusable", and recommends against it when possible (aka outside of error handling & breaking from multiple loops as C does not have multi-level break).

Re:The Evolution of C Programming Practices: A Study of Unix... by zzzcpan on Friday May 11, 2018 @08:45AM (#17046885)
Unstructured and unrestricted equivalent of goto then is a method call in OOP. Where method is basically a label and object is a shared state it randomly messes with.
Re:The Evolution of C Programming Practices: A Study of Unix... by coldtea on Friday May 11, 2018 @10:48AM (#17047658)
That's not unrestricted though -- control returns to the caller after the end of the function.

With goto that's not guaranteed to be the case -- that was the spaghetti part.

Re:The Evolution of C Programming Practices: A Study of Unix... by zzzcpan on Friday May 11, 2018 @06:22PM (#17051148)
No, that's not a restriction, but just a behavior. It doesn't keep you from jumping all over the place and modifying shared state by calling methods within methods. You can only use conventions to have some restrictions and structure here. Just like with goto.
Re:The Evolution of C Programming Practices: A Study of Unix... by goalieca on Friday May 11, 2018 @08:59AM (#17046949)
if (False) goto error;

vs.

if (False) throw ExceptionE;

Re:The Evolution of C Programming Practices: A Study of Unix... by Gibbon1 on Friday May 11, 2018 @12:10PM (#17048483)
Ehem

   if(False) longjump(error, 1);

   vs

   if (False) throw ExceptionE;
Re:The Evolution of C Programming Practices: A Study of Unix... by hindsightRegret on Friday May 11, 2018 @05:52PM (#17051027)
Good job, compiler :)
Re:The Evolution of C Programming Practices: A Study of Unix... by jimmy1 on Friday May 11, 2018 @11:59AM (#17048352)
You highlighted in this comparison why I hate exception handling in OOP languages, and just generally the common practices prescribed for handling errors.
Re:The Evolution of C Programming Practices: A Study of Unix... by kazinator on Friday May 11, 2018 @08:07PM (#17051625)
switch is unstructured to a large degree:

  switch (val)
    while (cond)
    {
      case 42: /* wee: if val is 42, we go straight here */
        break; /* this belongs to the while! */
    }

I have written this kind of jig the past:

   if (...) {

   } else switch (val) for(;;) {

   }
:)
Re:The Evolution of C Programming Practices: A Study of Unix... by colanderman on Friday May 11, 2018 @09:55AM (#17047287)
Yep. Those maligners forget that state machines are useful ways to structure code, are inherently analyzable (they form the basis of modeling languages like PlusCal), and can only be fully expressed in C using goto.

(No, you can't use tail calls to represent state machines in C; that is not a feature of the C language but rather of a given implementation. And yes, you could model state machines with an enum variable and a big switch statement, but that's even harder to follow.)

What trips people up is when goto is used to jump across resource lifetime boundaries (which C++ addresses with RAII), when they maintain too much state in cross-state variables that they forget what their invariants are, and when they use a goto as a replacement for what should be a function call.

Using goto to implement e.g. a data processing loop, a non-recursive graph traversal algorithm, or a parsing state machine are all perfectly valid uses.

Re:The Evolution of C Programming Practices: A Study of Unix... by kevin_thibedeau on Friday May 11, 2018 @10:49AM (#17047664)
Tracing through goto spaghetti is not more comprehensible than a structured switch with clearly defined regions for each state. This is the sort of abuse that gives goto a bad name. The only thing worse is table driven state machines calling function pointers scattered everywhere.
Re:The Evolution of C Programming Practices: A Study of Unix... by colanderman on Friday May 11, 2018 @10:59AM (#17047734)
State machines implemented with gotos have very clearly defined regions for each state: the space between each label. Switch-based state machines are fine, but become hard to follow when e.g. you need a loop around a couple states, and are often abused to allow changing states from a non-lexically-local context (e.g. within a function call).

At a high level, this:

    goto NewState;
is no less comprehensible or spaghetti-prone than this:

    state = NEW_STATE;
    break;
Re:The Evolution of C Programming Practices: A Study of Unix... by kbumsik on Friday May 11, 2018 @01:02PM (#17048945)
That’s what I am thinking of. These days people use goto only to reduce spaghetti code in very specific use cases in C and nothing more.
Re:The Evolution of C Programming Practices: A Study of Unix... by WalterBright on Friday May 11, 2018 @08:41AM (#17046856)
As a longtime C and goto user, defending the practice many times, I discovered something interesting.

My uses of goto can be replaced with nested functions! The code is nicer, cleaner, and the equivalent code is generated (the nested functions get inlined).

Of course, nested functions aren't part of Standard C, but they are part of D-as-BetterC. (D has goto's too, but I don't need them anymore.)

Re:The Evolution of C Programming Practices: A Study of Unix... by naveen99 on Thursday May 24, 2018 @09:54AM (#17143968)
Walter, what do you think of nested functions or even normal functions taking an identifier similar to continue / break to be able to jump up the stack precisely: either a certain number of steps, or to a particular calling function.

https://dlang.org/spec/statement.html#continue-statement

also, what do you think of a partial compilation feature / tree shaking https://webpack.js.org/guides/tree-shaking/

Re:The Evolution of C Programming Practices: A Study of Unix... by bgongfu on Friday May 11, 2018 @12:50PM (#17048841)
Just wanted to mention that GNU C has supported nested functions since forever, it's one of the main reasons I prefer GCC over Clang these days.
Re:The Evolution of C Programming Practices: A Study of Unix... by buserror on Friday May 11, 2018 @03:50PM (#17050350)
Yes and it annoys me no end that clang has refused to implement them as well, as they were part of my codebase as well... How better to implement stuff like qsort() callbacks than with a simple, contextual small function just over it ??

YES it is dangerous due to stacks etc etc but hey, we're grown up adults, not script kiddies.

Re:The Evolution of C Programming Practices: A Study of Unix... by basementcat on Friday May 11, 2018 @05:47PM (#17050998)
Clang has Blocks instead of nested functions. There may be patches for gcc-4.2 for Blocks but they didn't make it to the mainline.

https://en.wikipedia.org/wiki/Blocks_(C_language_extension)

Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Saturday May 12, 2018 @02:14AM (#17052723)
> YES it is dangerous due to stacks etc etc but hey, we're grown up adults, not script kiddies.

That is how CVEs are born.

Re:The Evolution of C Programming Practices: A Study of Unix... by bgongfu on Saturday May 12, 2018 @06:06AM (#17053329)
Using a chainsaw without paying attention is how fingers are cut off, using that as an argument against making chainsaws easier to use doesn't make any kind of sense.
Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Saturday May 12, 2018 @10:31AM (#17054213)
Good chainsaws have protection mechanisms builtin.

C does not.

Re:The Evolution of C Programming Practices: A Study of Unix... by bgongfu on Sunday May 13, 2018 @06:52AM (#17058285)
Good for you maybe, projecting that on people who have a clue what they're doing doesn't make sense either. They're mostly messing up chainsaws as well these days, for the same misguided reasons.
Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @09:31AM (#17047165)
That adds a lot of boilerplate though. IMO the best solution is destructors and RAII so that you can return early in case of error and not leave your resource half-initialized. And this way you don't have to repeat your cleanup code in the "deinit" method. Of course if you start adding destructors soon you'll want generics and before you know it you end up with "C with classes" and we all know that's the path towards insanity.
Re:The Evolution of C Programming Practices: A Study of Unix... by WalterBright on Friday May 11, 2018 @10:15AM (#17047421)
> That adds a lot of boilerplate though.

In practice, it doesn't. (The compiler inlines the code.) I know because I'm pretty picky about this sort of thing - it was why I was using goto in the first place.

> RAII

RAII can work, but it's a bit clunky compared to a nested function call. Additionally, if the code being factored is not necessarily the same on all paths, that doesn't fit well with RAII.

Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @10:45AM (#17047634)
Boilerplate in term of characters typed, not resulting code size. Adding a bunch of function declarations adds a significant amount of noise IMO.

>RAII can work, but it's a bit clunky compared to a nested function call. Additionally, if the code being factored is not necessarily the same on all paths, that doesn't fit well with RAII.

I think I'd need to see an example of what you're talking about then because I don't quite understand how your method works exactly.

Re:The Evolution of C Programming Practices: A Study of Unix... by vardump on Friday May 11, 2018 @01:47PM (#17049367)
Boilerplate doesn't mean (binary) bloat.
Re:The Evolution of C Programming Practices: A Study of Unix... by WalterBright on Friday May 11, 2018 @02:11PM (#17049570)
Rather than debate, here's an example of replacing goto's with a nested function:

https://github.com/dlang/dmd/pull/6656/files

Re:The Evolution of C Programming Practices: A Study of Unix... by vardump on Friday May 11, 2018 @02:49PM (#17049877)
I guess it's a matter of taste, but I often (not always) prefer less return statements in a function with gotos to error handling/cleanup code. Especially in kernel mode drivers.
Re:The Evolution of C Programming Practices: A Study of Unix... by WalterBright on Friday May 11, 2018 @02:56PM (#17049944)
Check the asm code generated by your compiler - it may optimize multiple returns into one.
Re:The Evolution of C Programming Practices: A Study of Unix... by vardump on Friday May 11, 2018 @05:06PM (#17050806)
Not performance or code size I'm concerned, it's mainly about correctness. Stuff like input validation and releasing a spinlock in kernel code.
Re:The Evolution of C Programming Practices: A Study of Unix... by hzhou321 on Friday May 11, 2018 @02:07PM (#17049536)
> My uses of goto can be replaced with nested functions

I guess you are not using goto as flow-control then.

Re:The Evolution of C Programming Practices: A Study of Unix... by WalterBright on Friday May 11, 2018 @02:12PM (#17049581)
That's what I would have said until I tried it :-), and why I said it was interesting!
Re:The Evolution of C Programming Practices: A Study of Unix... by 0xcde4c3db on Friday May 11, 2018 @09:01AM (#17046965)
> It bothers me when "goto" is assumed to be "a maligned language construct".

That's a statement about what people say about the feature, not about the feature itself. The subtlety here is that malign as an adjective refers to something evil or ill-intentioned, while as a verb it means something closer to slander or defame. It's frequently (mostly?) used in a context of skepticism regarding the claims in question, especially in the construction much-maligned.

Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @09:40AM (#17047212)
Sounds a bit like a strawman then, does anybody actually maligns "goto" as an error handling construct in C? It's pretty standard in my experience. It's goto "like in BASIC" that's utterly evil and rightfully maligned. And having learned C coming from BASIC I speak from experience...
Re:The Evolution of C Programming Practices: A Study of Unix... by MikkoFinell on Friday May 11, 2018 @10:18AM (#17047436)
Yes actually. Our teacher in university described it as "Something really bad".
Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @01:19PM (#17049114)
In the context of C or C++? I've read similar warnings in C++ tutorials in the past and I tend to agree with them, in C it's just silly however.
Re:The Evolution of C Programming Practices: A Study of Unix... by MikkoFinell on Friday May 11, 2018 @01:28PM (#17049204)
In the context of a C systems programming class.
Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @08:20AM (#17046706)
Yeah their take on goto is a bit odd given that it's probably the sanest way to do "cascading" error handling in C given that we don't have RAII or exceptions.
Re:The Evolution of C Programming Practices: A Study of Unix... by nierro on Friday May 11, 2018 @10:51AM (#17047678)
GCC supports RAII through cleanup variable attribute (https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...) though.
Re:The Evolution of C Programming Practices: A Study of Unix... by enriquto on Friday May 11, 2018 @09:20AM (#17047085)
For small and moderate memory requirements, C pretty much supports RAII via variable-length arrays.

You just replace this:

    void f(int n)
    {
            float *x = malloc(n * sizeof*x);
            // ...
            free(x);
    }
with this:

    void f(int n)
    {
            float x[n];
            // ...
    }
edit: and you can exit your function anywhere without leaking.
Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Friday May 11, 2018 @11:19AM (#17047908)
They were made optional, as it turned out a very bad idea regarding security.

I just need to call your example function with the right n to corrupt the stack.

Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @09:34AM (#17047179)
For memory allocs sure, but that's only a small subset of resource management. How about sockets, fds, locks, 3rd party library initialization, hardware setup (for device drivers) etc... Alloca doesn't cut it, you need general purpose destructors.
Re:The Evolution of C Programming Practices: A Study of Unix... by Const-me on Friday May 11, 2018 @10:34AM (#17047550)
Also when you code something at lower levels, sometimes it’s beneficial to treat some parts of CPU state and thread state as resources: process/thread priority, interrupt mask, FPU control, even instruction set (e.g. Thumb support on ARM needs to be manually switched on/off).
Re:The Evolution of C Programming Practices: A Study of Unix... by enriquto on Friday May 11, 2018 @09:40AM (#17047215)
sure, it's just a small, but non-negligeable, part of RAII that you can do in C
Re:The Evolution of C Programming Practices: A Study of Unix... by zzzcpan on Friday May 11, 2018 @10:19AM (#17047447)
It's negligible, you still need to manage lifetimes somehow beyond the scope of a single function. Like having a context abstraction and tying destruction of resources to it. Introducing something alternative for special cases only increases complexity as now instead of using a single universal and consistent API you have multiple that behave rather differently.
Re:The Evolution of C Programming Practices: A Study of Unix... by enriquto on Friday May 11, 2018 @10:28AM (#17047509)
in many cases (I would say most, at least for my programs in non-interactive scientific computing), all the objects can be created at the beginning of the program, and then no further creation happens. Sometimes it takes a bit of effort to refactor your program into that structure, but it is an effort well spent. Then you can use tools like openbsd's pledge, and reason more clearly about your algorithms.
Re:The Evolution of C Programming Practices: A Study of Unix... by simias on Friday May 11, 2018 @10:53AM (#17047692)
I concur, that tends to be my modus operandi as well but unless your application is completely monolithic you'll probably have 3rd party init code to deal with at some point. And again it won't help if you need to handle cleanup that's not memory-related.

In the case of an operating system (the subject of TFA) pre-allocating everything is obviously completely impractical and alloca won't help since you can't return the memory outside of the stack frame. I'd wager that there are very few uses of goto in kernel code that could successfully be replaced by alloca (the fact that kernel stacks tend to be very shallow wouldn't help either).

Re:The Evolution of C Programming Practices: A Study of Unix... by Too on Sunday May 13, 2018 @03:46AM (#17057792)
Pre allocation is generally the safe option in a embedded security critical environment where you must always handle the worst case scenario and you know all possible inputs. In a user interaction environment though it's usually better to over-sell so that the user can choose wheter he wants to create 1 million A's or 1 million B's, instead of having a pre-created pool of half a millon A and Bs each.

With pre allocation you usually also end up creating your own resource management within the pre allocated pool and then you are back to the resource management problem...

Re:The Evolution of C Programming Practices: A Study of Unix... by richard_todd on Friday May 11, 2018 @09:35AM (#17047184)
RAII is about a lot more than freeing memory. What if that’s an array of open file handles? Or mutex locks, etc?
Re:The Evolution of C Programming Practices: A Study of Unix... by tom_ on Friday May 11, 2018 @10:46AM (#17047642)
Re:The Evolution of C Programming Practices: A Study of Unix... by enriquto on Friday May 11, 2018 @11:20AM (#17047920)
yeah, just like ieee754 floating point arithmetic. What's the point of your remark?
Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Friday May 11, 2018 @08:22AM (#17046719)
It is, as an unstructured "anything goes" statement.

As for continue, break, and return, they have an explicit workflow, existing or resuming the current scope.

The only language where unconditional jumps make sense is Assembly.

The last time I actually wrote a goto statement was probably in some BASIC dialect.

Re:The Evolution of C Programming Practices: A Study of Unix... by CodeArtisan on Friday May 11, 2018 @10:33AM (#17047546)
>The only language where unconditional jumps make sense is Assembly.

In Scheme, because a lambda expression is a closure and shall be optimized with tail call elimination, it is considered as the ultimate goto. It's goto but with procedural abstraction.

Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Friday May 11, 2018 @10:51AM (#17047682)
Yes, which means you are sure where the flow goes next, instead of hunting down goto spaghetti.

Even call/cc is more structured than plain gotos.

Re:The Evolution of C Programming Practices: A Study of Unix... by CodeArtisan on Friday May 11, 2018 @11:31AM (#17048037)
I am not sure about that. What about high order programming

    (define (goto proc) 
      (proc))
Re:The Evolution of C Programming Practices: A Study of Unix... by pjmlp on Friday May 11, 2018 @11:33AM (#17048075)
It still has a call stack, goto only goes forward.
Re:The Evolution of C Programming Practices: A Study of Unix... by jdblair on Friday May 11, 2018 @04:38PM (#17050631)
Using goto for managing cleanup after an error condition results in cleaner, easier to understand and maintain code. This is a specific idiom that is easy to recognize.

On the other hand, using goto to jump back in the program flow, or multiple branching gotos are both asking for trouble.

Re:The Evolution of C Programming Practices: A Study of Unix... by kbumsik on Friday May 11, 2018 @01:27PM (#17049191)
For people who say goto statements make spagetti, please consider looking at this goto use case in Linux, sock_create_lite() [1]. Imagine we make the same thing without goto here, is it gonna be more Don't-Repeat-Yourself, more readable, and less error-prone? I don't think so.

I understand the how hamful goto statement is in general all of us know that. But there is very specific useful area in C. When Dijkstra wrote "GOTO Statement Considered Harmful", even before C was born, people tended to use goto statements everywhere because they were used to use assembly jump instructions. But we don't abuse goto statments anymore.

[1]: https://github.com/torvalds/linux/blob/master/net/socket.c#L...

Re:The Evolution of C Programming Practices: A Study of Unix... by coldtea on Friday May 11, 2018 @10:46AM (#17047644)
return is ok -- continue and break are also problematic, but at least are isolated in the same context (e.g. function).

goto is ok only for local error cleanup (or auto-generated code, e.g. for parsers etc).

Re:The Evolution of C Programming Practices: A Study of Unix... by haikuginger on Friday May 11, 2018 @09:21AM (#17047097)
As a C novice, this makes me wonder - wouldn't templates/macros be able to serve a similar purpose to goto statements if the goal is to avoid nested calls but still share code?

EDIT: Or, for that matter, trusting the compiler to inline small-enough function calls?

Re:The Evolution of C Programming Practices: A Study of Unix... by Gibbon1 on Friday May 11, 2018 @12:45PM (#17048819)
> wouldn't templates/macros

A gcc extension that gets around macros is nested functions.

> trusting the compiler

99.99% of the time you should just trust the compiler to do the right thing. That 0.01% of the time use a well tested and maintained library.

Hating on goto in c is just cargo cult programming. goto in BASIC and FORTRAN are evil. Though back in the 1960's 1970's programmers often had no choice. Programmers used evil assembly goto hacks in order to get their programs to fit in memory/disk.

Problem with Dijkstra was he was a academic mathematician who despised practical programming where the program needed to run on the hardware available. Hint back in the 1970's professors like Dijkstra had unlimited accounts on the schools mainframe where everyone else had extremely limited accounts.

Re:The Evolution of C Programming Practices: A Study of Unix... by zengid on Friday May 11, 2018 @01:29PM (#17049228)
The authors even concede that goto may be useful if not dangerous:

Perhaps goto is too valuable to let go; or letting it go results in code that is more complex than simply using it judiciously.

Re:The Evolution of C Programming Practices: A Study of Unix... by gymshoes on Monday May 14, 2018 @02:58AM (#17063344)
I saw in a Computerphile video that gotos are not recommended in high level languages because you have the while loop for that.