why is it illegal to use "goto"?

Ғылым және технология

Should you use goto statements? What does a goto statement even do? Why are they bad? or... are they? In this video, we talk about what a goto statement is, when it's bad to use them and how to use them well in your code!
🏫 COURSES 🏫 Learn to code in C at lowlevel.academy
📰 NEWSLETTER 📰 Sign up for our newsletter at mailchi.mp/lowlevel/the-low-down
🙌 SUPPORT THE CHANNEL 🙌 Become a Low Level Associate and support the channel at / lowlevellearning
Why Do Header Files Exist? • why do header files ev...
How Does Return Work? • do you know how "retur...
🔥🔥🔥 SOCIALS 🔥🔥🔥
Low Level Merch!: lowlevel.store/
Follow me on Twitter: / lowleveltweets
Follow me on Twitch: / lowlevellearning
Join me on Discord!: / discord

Пікірлер: 745

  • @LowLevelLearning
    @LowLevelLearning7 ай бұрын

    wanna get good at programming? check out lowlevel.academy and use code THREADS20 for 20% off lifetime access. or dont. im not a cop

  • @pepsitoly

    @pepsitoly

    7 ай бұрын

    What standard of C do you use in this course? I hope it's ANSI c89. I really enjoy your videos, you are one of the persons that inspired me to learn C. And the project you've picked is just brilliant. I just wish to finish Herbert Schildt C++ Reference (only C part) and Dennis Ritchie C programming language books before starting your course, I hope it makes sense

  • @miboxtv_maison9193

    @miboxtv_maison9193

    7 ай бұрын

    There is an other way where using goto is more readable. Make break with multiple loop. Without goto, we have to define an exit variable, and the test statement of the loop looks unreadable.

  • @kameronbriggs235

    @kameronbriggs235

    14 күн бұрын

    There are loops which are impossible without goto.

  • @AstroTibs
    @AstroTibs24 күн бұрын

    "GOTOs make your code unreadable, therefore code without GOTOs is readable" is the "denying the antecedent" fallacy.

  • @DerPinguim

    @DerPinguim

    21 күн бұрын

    Also annoyed me a bit

  • @jimnoeth3040
    @jimnoeth30407 ай бұрын

    I've been programming for over 50 years and goto has a definite place in the toolbox. Now for highly structured languages such as C/C++, Java, etc. goto can be somewhat confusing. But for procedural languages such as cobol (yes, cobol is still used today), Fortran, etc. goto can actually make the code more readable and, moreover, more efficient. For assembly language, goto is a necessity.

  • @elpatosilva

    @elpatosilva

    7 ай бұрын

    Edsger Dijkstra probably hates you. Just like BASIC

  • @anon_y_mousse

    @anon_y_mousse

    7 ай бұрын

    It annoys me when people group C and C++ together as though they're the same language. It was already easy to make a program that was valid in one but invalid in the other by C99, but now it's nearly impossible to not hit that wall. Java kind of pisses me off due to how little foresight they had in designing it. Not merely removing goto but making it a reserved keyword that generates an error at compile time, and then they had to add functionality to break and continue just to make up for the deficiency which caused a lot of problems that C++ already solved but in a more elegant way while still allowing you to use goto for those problems where it was still somewhat necessary. I guess what I'm driving at is that these ideological stances that people take based on inexperienced programmers misusing tools leads to garbage language design as well as garbage program design and I wish the lies that perpetuate them would stop cropping up. The old Knuth quote about premature optimization really irks me too.

  • @anon_y_mousse

    @anon_y_mousse

    7 ай бұрын

    @@bb-sky But it *is* telling it to continue, from the top of the loop. Though, I wouldn't be opposed to using next as the keyword to start the next iteration of a for loop, it wouldn't make sense in the context of a while or do/while loop, and in the interest of lowering the keyword count I'd delete the one that's the odd man out.

  • @anon_y_mousse

    @anon_y_mousse

    7 ай бұрын

    @@bb-sky Interesting perspective. But you'll have to come up with a better word than next or skip to convince me. I can't think of a word that's more apt than continue, only phrases.

  • @1sthaloman

    @1sthaloman

    7 ай бұрын

    @@anon_y_mousse restart?

  • @ChunGzter
    @ChunGzter7 ай бұрын

    You can also write a function that does this for you and call that function with different parameters if you are scared of the unstoppable errors that might come with this approach.

  • @talkysassis

    @talkysassis

    7 ай бұрын

    This can lead to some ugly bugs by getting the file pointer on another scope

  • @GuentherJongeling-hu6oe

    @GuentherJongeling-hu6oe

    7 ай бұрын

    Function calls add quite a bit of overhead compared to goto statements, unless they're inlined (which from my experience doesn't happen very often)

  • @lMINERl

    @lMINERl

    7 ай бұрын

    ​@@talkysassisuse rust if you want to be safe and 0.001 ms wont make a difference, for some embedded systems you have limited size and memory.

  • @TheRobbix1206

    @TheRobbix1206

    7 ай бұрын

    Splitting the logic of the function with it's error path in another function tends to make things much messier and make easier bug as you need to sync the error with your function in any case. You also might pass a crazy amount of params of your function to your error function !

  • @jeffery_tang

    @jeffery_tang

    7 ай бұрын

    but with a function you can't break, continue, or return from the function that it was called from

  • @ishi_nomi
    @ishi_nomi7 ай бұрын

    Yeah agree. The error handling case mentioned here and sometimes breaking multi-layers of for loops is where goto make more sense than normal control flow. They are literally everywhere even in source code of linux kernel.

  • @georgerogers1166

    @georgerogers1166

    7 ай бұрын

    Or exiting a loop in a switch.

  • @nolanfaught6974

    @nolanfaught6974

    7 ай бұрын

    Their use is recommended in the kernel to support a “centralized control flow” method of coding

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    Its because normal control flow is lacking in the C language. Something like "try/finally" , I don't know.

  • @jbird4478

    @jbird4478

    7 ай бұрын

    @@monad_tcp try/finally is not normal control flow but exception handling, which requires quite a lot of runtime support. C is just too low level for that. That's not to say you can't implement it in C, but it's not part of the standard language because that is designed to be portable across a huge amount of different systems. Try/finally requires stack unwinding, which is very system specific. With gcc, exception handling for C++ is actually implemented in C. Under the hood of course, all control flow eventually boils down to a form of 'goto'.

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    @@jbird4478 try/catch/finally is control flow. It changes the point where the execution of code is going, therefore it is a control flow statement, compared with all the other nodes in the AST that are considered expressions, not statements. I'm using a formal definition here. (not the C programming language specification, but more general) You might correctly argue that C is low level for that sort of control flow, you might be right, C is a "mere" macro-assembler. On the other hand, even function calls might be considered special "control flow" as the C programming language does run in hardware without a stack. All of that is merely an implementation detail. But you do have a point.

  • @kuhluhOG
    @kuhluhOG7 ай бұрын

    Imo discussing why GOTO is shunned without talking about what it actually was when "GOTO considered harmful" was written does the discussion a misservice. So, GOTO at the time a lot more powerful than what C is able to do. It was not only in most languages the primary way of handling control flow, it was also able to jump across function boundaries. Here an example (in C syntax because reasons): void f(int i) { label: print(i); } void g() { goto label; } This lead to the problem that you couldn't think of function like a black box. You needed to know what it does if you want to reason about your code. And because EVERY function was able to do that, you needed to practically know the contents of EVERY function. And guess what, stuff like this was so widely done, that at the time "GOTO considered harmful" was published it was highly controversial ("You want to say I am not capable of doing this safely?").

  • @Optimus6128

    @Optimus6128

    4 ай бұрын

    That's good to know, I didn't consider it used to work like this. I was always under the impression that the label has to be in scope, so it's not easy to abuse it. Maybe in older versions of C and compilers without following the standards. And the article would make sense then if people did this regularly. I don't even know how that would work, because if in your example g() jumped to label in f(int i), then what the hell is the value of i at that point? Why would anyone do that even if allowed? But thinking about, we have much worse things nowadays that will actually break the flow, something inside scope affecting things outside scope even without you realizing it.

  • @xwtek3505

    @xwtek3505

    2 ай бұрын

    I can't imagine how the code snippet should do other than undefined behavior

  • @kuhluhOG

    @kuhluhOG

    2 ай бұрын

    @@xwtek3505 as I said, in C it would not even compile in the languages back then? well, UB wasn't really termed well yet and everything not otherwise defined was "implementation defined behaviour"; so, yeah, it worked because programmers looked at what the implementation actually did, and then used that to their advantage not with undefined behaviour, that's not really possible anymore since what is being done under the hood is more often than not unpredictable I would argue that we are worse off know in that department nonetheless, goto thankfully can't jump outside of functions anymore

  • @Stratelier

    @Stratelier

    Ай бұрын

    I think scope restrictions are a major part of why GOTO got deprecated to begin with. Even at the lowest level, if you GOTO a code point that's inside a different function scope, then it encounters a RETURN (without having first called said function in the usual manner) the return address it pops from the stack may be anything from unpredictable to actual garbage -- likewise, references to local variables pushed onto the stack may return unpredictable/garbage values.

  • @oddcraft18

    @oddcraft18

    Ай бұрын

    Bro u need goto ur gonna miss out on 0.1us

  • @deedoubs
    @deedoubs6 ай бұрын

    Goto is fine, just don't go up.

  • @MrAB-fo7zk

    @MrAB-fo7zk

    Ай бұрын

    You're 100% right .. Read any major projects that power major infrastructure (all C... Hmm) ... You'll see lots of goto, always down to an error condition. It's a pretty common trope in C. Nothing wrong with it.

  • @deedoubs

    @deedoubs

    Ай бұрын

    @@MrAB-fo7zk Not *always* down to an error condition, sometimes you just want to skip over a block of code because a condition is met and it's cleaner than nesting that block within a large if clause. Bottom line though is that as long as you are using it to move down from where you are at the same level of brackets, you are absolutely fine. It only gets sketchy when you start using it to go up (IE creating a loop) or to the right (IE you are jumping into a condition or a loop). That's where people start getting themselves into trouble.

  • @MrAB-fo7zk

    @MrAB-fo7zk

    Ай бұрын

    @@deedoubs you're right, I meant to say just "usually" for an error condition, not always or that it must be for that purpose!

  • @jnharton

    @jnharton

    21 күн бұрын

    The important thing is to maintain a consistent, traceable flow of execution. You can make a real mess of spaghetti code using goto.

  • @jnharton

    @jnharton

    21 күн бұрын

    @@MrAB-fo7zk That is because a GOTO is a excellent way to abruptly escape out of a function or even the whole program when a serious error occurs. Java does something similar with Unchecked Exceptions (aka a runtime exception), which the programmer is not required to handle. A very common example to come across is the NullPointerException, which usually means that a reference which was expected to point to a valid object is /null/. E.g. It's like a restaurant receiving a takeout order without any customer information or which either contains items that aren't on the menu or none at all. --- I.e. there's little nothing you can do with it besides discard it

  • @Anubis1101
    @Anubis11017 ай бұрын

    yea people who unilaterally dismiss a basic thing like goto as bad just make it harder and more confusing for new programmers to figure out how stuff works and what they should be doing. everything has a purpose, and most things have good and bad ways to use them.

  • @Trekiros
    @Trekiros7 ай бұрын

    I've only had to use a goto once in ten years, to escape a highly-nested for loop. I could have "unrolled" the for loop and turned it into 5 functions, but I tried that, and it resulted in a code that was less readable than with a simple goto. My boss fought me for it, but in the end, dogmas and tradition matter less than producing code our teams can actually use and maintain easily.

  • @drachefly

    @drachefly

    5 ай бұрын

    couldn't you have used a labeled break?

  • @xeridea

    @xeridea

    5 ай бұрын

    @@dracheflydepends on the language, some languages support specifying now many loops to break, which is error prone, and/or some have labeled breaks, while others don't. I would say goto is essentially a labeled break, since this is the only real use I see in it in 99.9% of cases. It is still clean because the jump is directly after the loop to be broken, so you don't make spaghetti like this video made.

  • @amigalemming

    @amigalemming

    Ай бұрын

    @@drachefly or put the loop in an extra function and leave both the loop and the function with a 'return'.

  • @drachefly

    @drachefly

    Ай бұрын

    @@amigalemming That'd work too!

  • @simongido565

    @simongido565

    Ай бұрын

    @@amigalemming Exactly what I had in mind.

  • @metal571
    @metal5717 ай бұрын

    In C, handling errors in resource acquire/release is already error prone, and goto specifically for this case and only for forward jumps reduces human error. This is a common pattern in kernel code itself. If you're using C++, you'd be doing it wrong by using goto since we've got Resource Acquisition Is Initialization there.

  • @IBelieveInCode

    @IBelieveInCode

    7 ай бұрын

    Agreed.

  • @niewazneniewazne1890

    @niewazneniewazne1890

    7 ай бұрын

    The important part is once you're in a label you can't define new varriables within the label, which pretty much does limit the usefullness of gotos as a tool for error handling; The only other way I used gotos is for EINTR to avoid using: do { } while (ret (== || !=) -1); As it introduces the issue that you might forget to break out of the loop if you use the wrong statement;

  • @gustavoholo1007

    @gustavoholo1007

    7 ай бұрын

    Did you study electrical engineering metal? I didn't expect you here I like your videos

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    what's not error prone in the C language of making errors? Oh, I should have more respect. I meant. Fastly making errors as fast was humanly possible.

  • @oglothenerd
    @oglothenerd7 ай бұрын

    Looking at C code where you check the return type to see if it is an error makes me so thankful that Rust has Option, and Result enums.

  • @kevinyonan9666

    @kevinyonan9666

    7 ай бұрын

    What advantage is that? You still have to check if it errors. Plus, you could make your own Result type from an inlined tagged union

  • @shadamethyst1258

    @shadamethyst1258

    7 ай бұрын

    ​@@kevinyonan9666You only have one way to check for error in rust, instead of checking for `NULL`, `-1`, `VALUE_ERR`, or whatnot, and then reading the `errno` or whatever mechanism is used to know what the error was. In rust you just add a `?` or you use one of the error handling methods provided by Option and Result - with most of them sharing the same name across the two types.

  • @TheSast

    @TheSast

    7 ай бұрын

    Agreed, can't live without them.

  • @oglothenerd

    @oglothenerd

    7 ай бұрын

    @@kevinyonan9666 The compiler warns you when you haven't taken care of a Result enum, and it also can only represent Ok() or Err() as its variants.

  • @user-vu8fm5vb4n

    @user-vu8fm5vb4n

    7 ай бұрын

    ​@@kevinyonan9666you are FORCED to handle the errors or else the compiler refuses to compile your code.

  • @captainfordo1
    @captainfordo17 ай бұрын

    Another use of goto is for breaking out of a nested loop.

  • @jordixboy
    @jordixboy7 ай бұрын

    If, while, for, underneath they are just "gotos"

  • @Proferk

    @Proferk

    7 ай бұрын

    in that analogy, everything in C is just syntactic sugar for the inline asm statement.

  • @fders938

    @fders938

    7 ай бұрын

    ​@@Proferk Hey, that's why C is just a macro assembler, right?

  • @aquapendulum

    @aquapendulum

    21 күн бұрын

    @@Proferk Any code we write that isn't 0s and 1s is just syntactic sugar for 0s and 1s!

  • @larjunmnath
    @larjunmnath7 ай бұрын

    Man you are the sole reason why I fell in love with assembly, couldn't thank you more.

  • @leightonmitchell2564
    @leightonmitchell25647 ай бұрын

    I was writing a parser, and I used goto because I wanted to break out of the switch statement inside a for loop. It was an elegant solution.

  • @georgehelyar

    @georgehelyar

    7 ай бұрын

    Another way to do this would just be to put it in a function and return out

  • @CottidaeSEA

    @CottidaeSEA

    7 ай бұрын

    @@georgehelyar Yes, but there's also no reason to pollute your interface with more functions if there is only one user of said function. One of the reasons why goto has become this hated thing is because goto was the cool thing to do at one point, which just sucked ass when done on a larger scale and very long jumps. Doing it to break out of nested loops or similar is totally fine.

  • @js46644

    @js46644

    7 ай бұрын

    ​@@CottidaeSEAwhy would an additional function necessarily be part of the interface?

  • @CottidaeSEA

    @CottidaeSEA

    7 ай бұрын

    @@js46644 How would it not be? If you suggest making the visibility private, reconsider that thought and think about what an interface is. I do not mean the keyword interface you're probably thinking of.

  • @keris3920

    @keris3920

    7 ай бұрын

    @@js46644 I agree with you, there is no reason to make the function part of the interface. It should just be a static free function, a private static member function, or not exported from a module.

  • @sinom
    @sinom7 ай бұрын

    In pure C stuff like this is an at least decent to good way of handling things. In most other languages you should rather use some sort of scope guards though (something RAII-like like objects in C++ and rust, or "using" resource statements in C# etc.)

  • @pheww81

    @pheww81

    7 ай бұрын

    And even if more modern low-level-like-c language like Zig where you don't have RAII (because no dtor) they added the statement defer and errdefer exactly to avoid this kind of code.

  • @BrotherCheng

    @BrotherCheng

    7 ай бұрын

    I think in C++ goto statements are also more complicated due to it being difficult to reason about RAII and object lifetimes in goto. At least I don't remember off the top of my head what the behavior is and I think a lot of programmers don't.

  • @shadowchasernql
    @shadowchasernql7 ай бұрын

    In general as a rule of thumb, I try to keep GOTOs in the same function scope, so just for loops and the like, it helps keep GOTO reasonably easy to read (and far safer!) but also still gives it a lot of flexibility. Also if I'm writing optimized code, I try to keep branches in general (not specifically GOTOs, they just tend to get messier), to be short and minimal, only things like small if statements, just to avoid the LOADS of cache misses you can cause by putting everything in their own function.

  • @NYKevin100

    @NYKevin100

    5 ай бұрын

    Note that in C, goto cannot be used to jump into a different function (mostly because it would be unclear what should happen when that function tries to return). You can use longjmp to do that, but only if the function is already on the call stack (i.e. it behaves a little bit like throwing an exception, but without proper language support). My advice is to avoid using backward gotos (prefer writing a loop), and to only use forward gotos to eliminate excessive nesting of if statements or duplicate code. Hand-constructed goto loops can be very difficult to understand, and simple if statements are usually more readable than if-goto compounds.

  • @valseedian

    @valseedian

    4 ай бұрын

    goto has one really important use for me that aligns with this- it's one of the only ways to short circuit out of a large nested loop algorithm without having to explicitly end each loop.

  • @xwtek3505

    @xwtek3505

    2 ай бұрын

    Is there a language that allows goto to a label in different function scope?

  • @valseedian

    @valseedian

    2 ай бұрын

    @@xwtek3505 c++ (at least the mingw compiler from experience, but I think any flavor) can do goto from any point to any other point and can cross scope. it is almost always undefined behavior to goto from one scope to another. notable examples of where it can be used is as a return from a void function to the main scope, calling into a function that returns void and uses no arguments, but you have to goto back out, and, it can be used to navigate self altering code if you have the balls to write it. I will use goto to leave nested loops if there's no good way and I'm relying on local variables heavily in the destination rather than refactoring it into a referencing function. c++, and c, will let you do all kinds of crazy bs. almost every combination of characters that compiles will result in a crashing program. it takes very specific sets of characters to result in a stable execution. there are many things you can code in c that will result in an undefined behavior, but a repeatabe result, and that gets used for what it actually does, whatever that is. if you want a Lang that doesn't spit out an executable if it has undefined behavior- go use rust and run into compiler walls

  • @valseedian

    @valseedian

    Ай бұрын

    @@xwtek3505 yes, c, c++ both allow you to goto between scopes. it's practically always undefined behavior. notable exceptions are as quasi function calls but you need to save the origin, and self altering code, if you have the coconuts --at least the mingw compiler will allow you to compile with these using certain flags.

  • @marshallscarpulla3032
    @marshallscarpulla30327 ай бұрын

    I always love this argument. Writing high level code without GOTOs creates more readable code. This is mostly true. The funny part is, the compiler generates tons of jumps (gotos) in the final binary, the actual assembly language. Just disassemble a switch statement, or if-then-else. JMP (goto) is there.

  • @iWhacko

    @iWhacko

    6 ай бұрын

    just because the compiler does it for you doesn't make it a good practice. Source code is meant to be readable, so make sure it is. If it wasn't we would all be programming in binary. Because that's what the compiler ultimately makes of it.

  • @marshallscarpulla3032

    @marshallscarpulla3032

    6 ай бұрын

    ​@@iWhacko ​ @JodyBruchon I think you replier's are missing my point. I've written code with high-level, mid-level, and low level languages for 35 years on a variety of embedded platforms and various computer systems and have always followed the standards of well written, highly commented code as every programmer should, so I will repeat this one little part again. I still find it funny that so much emphasis is put on NOT using gotos in code, even though the compiler has NO choice but to put jumps/gotos into the code at the BINARY level to make things actually work. So, at the lowest level, this no goto philosophy is bunk. Really good compilers do take into account the number of times an instruction cache would be cleared from branches, jumps, calls, and the level of optimizations selected during compile time can mitigate this problem. Some of the compliers are really really good at this, by actually counting instruction cycles and choosing the shortest paths. The bottom line is this. Assembly language can not exist without a jump instruction, but high-level/mid-level code can exist very happily without any goto statements.

  • @gloowacz

    @gloowacz

    4 ай бұрын

    ​@@iWhacko " Source code is meant to be readable". I have always stand on position that the source code is meant to create efficient and error-free binary. Readability is secondary. I have experience in nightmare projects that were killed by "good practices" and "code standards" and "clean code". Classic "measure becomes a goal" cases. Deadlines? Don't care, havta extract 5 more interfaces that will only ever have 1 implementation. Performance? Sorry, too busy renaming half of the functions in the project by adding "get" in front of the name. Bugs? Can't help, i am injecting 78th undebuggable maven dependency that obscures the logic behind reflection. Meanwhile i was able to recreate 80% of the project from scratch on my own spare time, using 50 classes that compiled in 10s. Not 2000 AbstractIntgerStringPrinterFactory classes that compiled for 15 minutes because of 2 GB of maven dependencies. But it was all "good practicies" while my code was too "tightly coupled" so they went with continuing the garbage. Project went under because of poor performance, bugs and crossed deadlines. Imagine my shock.

  • @jbird4478
    @jbird44787 ай бұрын

    This is basically the goto solution (pun intented) for handling errors in the Linux kernel.

  • @vodkacannon

    @vodkacannon

    25 күн бұрын

    That’s some very encoded humor.

  • @BlitterObject
    @BlitterObject7 ай бұрын

    Finally someone (else) that shows evidence where goto's are useful. Folks, goto's aren't evil; they're just another tool in the toolbox to use when it makes sense given all of the factors. (Singletons in other languages are similar in this way.) Having said this, part of determining "when it makes sense" is to not take it too far and abuse it.

  • @franciscofarias6385

    @franciscofarias6385

    7 ай бұрын

    People want shorthands that let them avoid thinking. Every tool is an asset, and you should have better reasons to use them or not than "someone told me so".

  • @loc4725

    @loc4725

    7 ай бұрын

    *"not to take it too far and abuse it"* I've been having some discussions with some Python programmers and they've been suggesting doing things like using the exception system for things other than raising and handling exceptions. It was a good reminder as to why things like GOTO are considered bad practice - if you metaphorically give some programmers a gun they will eventually shoot themselves. That said, GOTO in the event of an unhandleable exception in C is probably itself an acceptable 'exception' given the lack of a formal mechanism.

  • @anon1963

    @anon1963

    7 ай бұрын

    ​@@loc4725if you give anyone a gun* there

  • @jbird4478

    @jbird4478

    7 ай бұрын

    @@loc4725 Using exceptions for other things is very common in Python. You'll often see usage of 'KeyError' for example when something not being in a dictionary is just a normal expected state. I don't like it (but I don't like most of Python), but it's not a reason to ban exceptions from Python. Likewise, misuse of the goto statement is not a reason to ban it. You should just accept that some programmers will shoot themselves in the foot. There's no such thing as a good and also idiot-proof programming language.

  • @loc4725

    @loc4725

    7 ай бұрын

    ​@@jbird4478 There do appear to be quite a few, I guess you could call them 'mistakes' in Python. Looking at it's development history is like watching people learn what makes a language good / bad but with little knowledge of what came before and why certain features were dropped, added or made that way. Also I wouldn't "ban" exceptions and neither did I say that was a good idea. My problem stems from experience of how certain language features or paradigms end up being a problem because you cannot trust many programmers not to abuse them. And yes I agree, all you can do is limit the damage but then that is what a good high-level programing language should aspire to do. It shouldn't needlessly place scalpels on the dinner table or worse, force people to use them because there's no other choice.

  • @4115steve
    @4115steve7 ай бұрын

    Please consider making the course at one time payment. I think you would get more people to sign up. Thanks for making videos my main man

  • @Zullfix
    @Zullfix7 ай бұрын

    Thank you for making this video. Many people always scream at the sight of a goto without considering how it can be beneficial to the circumstance. I personally write C# more than anything else so I benefit from 'using' statements, however I still find gotos can be very useful when writing state machines or non-LINQ filtering logic.

  • @kuba4ful

    @kuba4ful

    4 ай бұрын

    In everyday's code I barely use goto, but when doing code challenges like LeetCode or CodeWars using C# where I tend to stay away from Linq (it's slow + it trivializes some challenges), that's when "goto" statement feels the most useful. It's more efficient both space-wise and time-wise.

  • @captmcneil

    @captmcneil

    27 күн бұрын

    This has little to do with 'using' - in C goto may be helpful because it lacks control structures like try-finally and its APIs rely so heavily on return codes. Which is a nice way of saying that C lacks proper tools for certain things, and goto is just the lesser of a bunch of evils. But that does not make it good or safe. When you have a language that gives you better options, use the better options. Goto breaks structured programming, and static analysis tools can't do their job properly without being able to make strong assumptions about the program flow. In C that may not be a big deal because you cannot make these kind of assumptions to begin with. But in modern C# static analysis is a big advantage. Tools rely heavily on knowing when something has been initialized and not, for example. In my experience many C folks cannot even appreciate that to its full extent because they have no experience with it. It would be foolish to compromise that just for something that might optimize the odd case by a few lines - and this is the reason why goto gets banned in so many projects. Please note, it's not at all about whether goto is sometimes useful. It's about principles: If a feature is a bit useful, but sometimes dangerous, and there is another option - always use the other option. Don't argue with me, Douglas Crockford says that a lot, and he's probably smarter than most people here. If you ever find yourself writing programs that look like that in Java or C#, step away from the computer. I don't argue about C, but as a senior lead developer and architect with 25+ years of experience, I say this with confidence: I have not seen one justifyable reason to use goto in C# application programming. Not even in 3D visualization or device driver code for industrial hardware.

  • @Minty_Meeo
    @Minty_Meeo7 ай бұрын

    My favorite use for goto in *C++* is to mimick the for-else pattern from Python. For the unaware, else statements on for loops will only execute if the loop concluded by its condition, rather than a break. With iterator-based for loops, it's as simple as moving the condition inside the loop body and turning it into a break (that way, you can add additional code to that specific exit path). For range-based for loops, that is not an option. Instead, the solution is to replace all breaks with gotos which skip past a block of code immediately following the for loop's scope. for (const auto& v : container) { if (some condition) goto LOOP_EXIT; SomeFunction(v); } std::println("All good!"); LOOP_EXIT: ...

  • @dontthrow6064

    @dontthrow6064

    7 ай бұрын

    Nice concept. Like when you have a piece of puzzle that almost fits and then you find the real piece.

  • @LittleRainGames

    @LittleRainGames

    6 ай бұрын

    Oh wow, didnt know that about for loops. Great to know

  • @PalladinPoker

    @PalladinPoker

    6 ай бұрын

    you could also do the following and skip using goto, although goto is cool. uint16_t i = 0; while (i { SomeFunction(i); } //destroy i

  • @Minty_Meeo

    @Minty_Meeo

    6 ай бұрын

    @@PalladinPokerI don't think that code does anything like what I wrote, but I think you were trying to suggest using the loop counter from outside the while loop's scope to detect if it terminated before reaching the loop_range? GOTO doesn't require an if statement to check the loop counter after the loop concludes, so GOTO is still better if that's what you're trying to suggest.

  • @gayusschwulius8490

    @gayusschwulius8490

    6 ай бұрын

    @@PalladinPoker That's WAY more inefficient due to the additional call and check, even more so if the outside function isn't inlined.

  • @ThePCxbox
    @ThePCxbox6 ай бұрын

    goto's are very handy in the case of gamedev - specifically when wanting to jump around within nested loops. Makes things 10x faster and organized if you do it right

  • @Rock48100

    @Rock48100

    3 ай бұрын

    Especially for text adventures

  • @CallousCoder
    @CallousCoder7 ай бұрын

    I always found it an academic discussion. Because as you and I know in assembly a goto (jump) is required. But in the extension of this discussion also was the “one return per function” something I break all the time these days.

  • @gregorymorse8423

    @gregorymorse8423

    7 ай бұрын

    Maintainability of code isn't an academic discussion. I'm sure everyone at your work place loves your spaghetti code lol

  • @CallousCoder

    @CallousCoder

    7 ай бұрын

    @@gregorymorse8423 you may not have watched this video then. The goto must go idiom is obviously not correct there are use cases where goto is a superior solution. Hence the clean code is not objectively true. And I can prove it even further, as jumps are Gotos and are the backbone of branching on a machine level. So the whole “clean code” religion breaks down the lower you go. Just like the idiotic “one return per function idiom”. It makes code unnecessarily more complex and slower. Then the “though shalt not repeat thyself” which is something you generally should stand by, but I have had situations where unrolling code is faster. And when there’s one situation where your “religion” doesn’t apply you can’t not should preach it as a fact. And “spaghetti code” what is that?! Is it a jump? Because a call to a different function is also a jump and you need to grab the listing of that code and read it to understand it completely. Every program exists of different strands of “pasta”. Ironically you can get far more list in Uncle Bob’s OOP world then a piece of assembly. Because it’s hard to find a single entry in complex frameworks like spring, spring boot, J2EE that have scheduled or event beams or even C++ which spawns many threads or systems with event messages. So even “spaghetti code” isn’t an objective truth. And it’s also a skill level! I’ve been developing software for 40 years. I find that the last 20 years I find it far easier to reverse engineer code than I did it the first 20 years. Just because I’ve seen more. The first time I saw self modifying code, back in 1988 I was like: “wtf? I don’t understand what is happening here. Why is a memory location in code space updates?” I spend literally a whole weekend experimenting with it and realized it’s power. And how I could reduce the amount of code needed and speed up for example joystick routines on the C64. Since I’ve seen self modifying code a lot and it’s just a matter of checking to see what opcode is set and it’s clear. So yeah, even “spaghetti code” is busted as an objective scientific fact. Unlike ohms law that always is R=U/I or gravity is always 9.8M/sec and doesn’t deviate on Sunday’s or has an exception on Mount Fuji. That is an objective scientific proof. It’s merely an academic discussion and personal preference that are not scientific facts. Because there’s an exception on everything Uncle Bob and his predecessors preached.

  • @SolidFake
    @SolidFake6 ай бұрын

    Cool, might actually make use of this in work next week. I had the issue that my C-code was too large to flash it on a microcontroller, and one thing I recognized was that I had such error-checks where each succeeding one only adds a line or two. Might give it a go (to).

  • @MarioDanielCarugno
    @MarioDanielCarugno7 ай бұрын

    Once upon a time I worked like that. We called 'epilogue' to labels at the bottom of each function to handle cleanup and having a single point of return. When goto was considered a 'bad word', exceptions were invented. Great video to remind that goto is not so bad, thank you

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    bool do_something_unguard(int *f) { } bool do_something() { bool b; int f = open(); if (f) b = do_something_unguard(f); close(f); return b; } // this gets boring fast, so does "goto exit:;" // its almost like there's a reason for try/finally to exist...

  • @spudbencer7179
    @spudbencer71794 ай бұрын

    So in the "good" example for using "goto" I have this question: Why not simply make a method to which I pass the necessary parameters and then call close on them? What's the advantage of the goto in comparison? I might have missed it. But the duplicate code is not a problem to me as I can outsource any duplicate code into a method that gets the necessary parameters and just call that method instead.

  • @apresthus87
    @apresthus877 ай бұрын

    This is the first time i've ever I just instantly went and bought a course from a KZreadr as soon as you mentioned the C course. I fell in love with C after years and years of using higher level languages but learning materials were a bit sparse so I'm super excited for this even though I'm not a beginner in C, I'll learn a lot I'm sure! :)

  • @thebuffman5597
    @thebuffman55977 ай бұрын

    I remember in our first C# class the first task the teacher gave us was "make a loop". I proceeded to write a goto variant for it with a break i made, the teacher was impressed but was like "okay, but please do the other way as this one is illegal" xd. The reasoning explanation he had made was that unlike regular loops, this would make a randomized selection or something and that it would result in slower program in a sense.

  • @lycanthoss

    @lycanthoss

    7 ай бұрын

    I don't understand what your teacher meant to say, but you should absolutely not be using gotos in C#. If you have to use a goto in C#, it is telling me one thing about your code - your function is too big and needs to be split into multiple functions.

  • @thebuffman5597

    @thebuffman5597

    7 ай бұрын

    @@lycanthoss Lol, I just said the teacher also said it was suboptimal, but he was surprised someone even knew about it, because people usually learning languages like python nowadays, etc. don't really learn this stuff at first. It was back when i started learning and wanted to be a bit funny. Like yeah, it's not a good way, but a funny way nonetheless to make an infinite loop. I'd never use it under normal circumstances. After asking around the only place where i could find use for gotos is maybe in kernel programming or so.

  • @insomnyawolf

    @insomnyawolf

    7 ай бұрын

    As some people already pointed out, they are just another tool in the box, and i am thankful for having them on C#, they are very rarely the way to go but it can make things a lot more clear and simple when used properly, but normal programmers rarely have the need. For me i find it very useful for conditional retry logic and for exiting nested loops those cases are kinda rare. You could argue that my code sucks then, but in that case i would like to learn a better way to do those that still work without overcomplicating simple things

  • @spearmintlatios9047

    @spearmintlatios9047

    6 ай бұрын

    What your teacher was probably talking about is ASLR, which randomizes addresses. This is implemented to prevent malicious attacks that tells the program to jump to an arbitrary line of code. If the attacker cannot be sure of the exact address of their desired code, then they cannot reliably execute arbitrary code or steal data.

  • @mage3690

    @mage3690

    6 ай бұрын

    The reasoning sounds like hocus pocus to me, why you _really_ shouldn't use it is because it makes everything harder to reason about. You could use a goto to implement ifs, fors, whiles, and functions, but just using the keyword designated for that purpose frees you brain up from having to follow the goto chain to figure out which one it is. Freeing up those mental clock cycles makes it easier to figure out whether or not your code goes into an infinite loop or any other bad state _before_ running it and having to use the debugger to figure out WTF is going on.

  • @hyper_lynx
    @hyper_lynxАй бұрын

    Just now learning that goto and longjump are different. I always assumed the issue with goto was that it does what longjump does and lets you jump into a different function with the wrong stack setup

  • @LogicEu
    @LogicEu7 ай бұрын

    Don't be afraid of gotos. At the core, the goto statement represents one of the most fundamental building blocks of computing; the jump. Without jumps there would not be touring completeness. I love the fact that C allows you to directly use these very low level bricks, as you can implement control flows that are impossible with ifs, switches, whiles and for loops. Once again, C gets you closer to your hardware and that's a feature, not a bug.

  • @lukekurlandski7653

    @lukekurlandski7653

    7 ай бұрын

    All you need for Turing completeness is if-statement and while loop (both if these use goto under the hood). In a small number of scenarios, goto might make your control flow simpler, but you can always achieve the same thing without it.

  • @sivorano

    @sivorano

    7 ай бұрын

    ​@@lukekurlandski7653I think you also need either goto or recursion for turing completness.

  • @LogicEu

    @LogicEu

    7 ай бұрын

    ​@@lukekurlandski7653 Yes! That's almost right! You don't actually need while loops, just if-statement and goto-statement actually. In languages like BASIC you don't get a built in loop statement, you just use ifs and gotos to go back en repeat the loop until a variable reaches a certain value. I kind of like that because it reflects how your computer actually execute your loops under the hood.

  • @roberthickman4092

    @roberthickman4092

    7 ай бұрын

    Its stupid that wasm was designed without a jump.

  • @Zooiest

    @Zooiest

    7 ай бұрын

    ​@@roberthickman4092 br and br_if

  • @videakias3000
    @videakias30004 ай бұрын

    I remember in highschool the book had an entire page saying how goto is the black sheep of computer commands and mentioned that some guy wrote an entire book against the goto. I wasn't taught back then how to use it and I wasn't taught how to use in the electronic engineering tei either(we only learned visual basic and c# there)

  • @alexandreparent3942
    @alexandreparent39427 ай бұрын

    And that's why we have C++ and RAII. No direct close. Things are released as it goes out of scope. If we don't want that... What about... Functions? They are gonna be inlined by the compiler. You could even not use early return and instead have the positive case in the if statement. Then cleanup is not duplicated. 3 alternatives to goto. Each with downsides. Each way more readable than goto. My main issue with goto is not even the obfuscation, it's scope switching. And that's not even considering you can goto a label inside another block to get some neat italian pasta.

  • @TheRobbix1206

    @TheRobbix1206

    7 ай бұрын

    That's because it was designed with C Ansi in mind which ask you to declare all your variable as the start of the function preventing any scope changing shenanigans

  • @sub-harmonik

    @sub-harmonik

    Ай бұрын

    I disagree with 'more readable', you're just introducing more control flow structures that actually make things less clear sometimes. for instance, you say use the positive case. but what if the 1st resource is positive but the second isn't? then you want to goto the negative case of the 1st resource to clean it up. (and actually that's the case in his example)

  • @AlFasGD
    @AlFasGD4 ай бұрын

    Another case I can think of is breaking out of a nested loop without introducing a one-shot flag variable, or likewise continuing the outer loop while inside the inner loop

  • @RavarYgamer212
    @RavarYgamer2126 ай бұрын

    I made a DFS klotski solver, and using a normal recursive function it gave me segmentation fault, but doing the recursive parts with goto worked flawlessly

  • @rasowa2958
    @rasowa29587 ай бұрын

    The very few times when I used GOTO in my C code was always for the reason shown in this video, to avoid duplication of a clean-up code before returning from the function.

  • @TheGrimravager
    @TheGrimravager5 ай бұрын

    Hey man, this is really cool. I wanted to compare the code before and after the goto statements. I wanted to check if a function call with a little refactoring wouldn't be an even better improvement, completely dropping the goto. A link to a gist or something would have been incredibly helpful for that.

  • @CottidaeSEA
    @CottidaeSEA7 ай бұрын

    I don't mind goto at all, but I think it should only be used in a very small scope. I think you can usually get a similar result through creating functions, so there is little need to actually have goto, but imagine you're searching for a specific value in a larger function and you have multiple nested loops for whatever reason. At that point you might actually want to have a goto in order to quickly break out of all loops. That is a perfectly valid use case in my eyes. The label is close enough to the goto for things to be understandable enough and you avoid having loads of breaks and if-statements. Could you just have made a function and returned the value when finding it? Sure. But sometimes you don't want to create a new function as it is not really a necessity in your use case. The goto will also be faster than doing if-statements every loop that break if true, which can matter a lot for larger data sets. So as long as you keep things simple enough, I think using goto isn't bad. Just don't do a bunch of branching logic with them. Only use them as fast exits out of nested loops and such and you're all good, avoid them if necessary though.

  • @xeridea

    @xeridea

    5 ай бұрын

    Breaking nested loops is the pretty much the only reason I see to keep goto around. There are some other possible very niche uses, but generally this can be improved by refactoring code to be cleaner. In this video, he turned 13 lines of code into 17, and made a mess out of it.

  • @D0Samp
    @D0SampАй бұрын

    Also if you're using C++, the compiler cleans up if you use goto to leave an inner scope just like with other control flow statements, but it may leave variables in an ill-formed state if you go past their declaration.

  • @crrodriguez
    @crrodriguez7 ай бұрын

    Remember that in the end the compiler will "goto" the living shit out your code..as much as it can to produce most efficient, compact code possible.

  • @Stratelier
    @Stratelier7 ай бұрын

    I remember even in late Visual Basic programming, there were sometimes esoteric cases where I actually resorted to those old GOTO/GOSUB statements. For example, VB doesn't have a "continue" feature inside loops, so if I needed to do that I'd label the end of the loop (e.g. "ContinueHere:") and GOTO that point.

  • @Hublium

    @Hublium

    6 ай бұрын

    It also specifically had the language feature "On Error GoTo ..." for the use case similar to the one shown in the video.

  • @Stratelier

    @Stratelier

    6 ай бұрын

    @@Hublium Yup, I remember using that. Especially when dealing with file I/O. A bit more dangerous was the "On Error Resume Next" which was super convenient if you needed to test just one call that might error out, but you had to remember to turn it off again (On Error Goto 0) or you've just suppressed all runtime errors globally until program execution terminates, potentially opening up all kinds of glitchy misbehavior downstream. Have fun debugging THAT!

  • @LeonAlkoholik67
    @LeonAlkoholik677 ай бұрын

    I'm gonna goto hell now

  • @strajkz
    @strajkz7 ай бұрын

    The one place I rather often use goto is in my custom installers, where I skip several steps or log an error and then jump to the end of a function without using a return. Yeah I could make function for each step and just do a return in case a bad return code matches, I however like to keep things as less convoluted with methods and functions in installers as possible, which in my past experience makes it easier to maintain.

  • @AidenElliott-ff2vt
    @AidenElliott-ff2vt6 ай бұрын

    Goto is also very useful for breaking nested loops.

  • @ProjSHiNKiROU
    @ProjSHiNKiROU7 ай бұрын

    For high-level language designers, thye must learn from examples where goto is essential in C and design features to avoid the need for goto, such as auto-dispose resources (RAII in C++ and Rust and using C#), or hand written state machines (async/yield).

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    The goto is literally not needed for any case whatsoever, in 20 years I couldn't fine any. Except the funny looking DuffyMachine, which is not even valid performance optimization anymore. Well, jumping from a statement to another in a switch would be a legal use for "goto", but you don't need it, just put the switch inside a for-loop and change the expression of the switch and do "continue". Hand written state machines can be created by mere function calls if you have a fix-point function to break the call-stack from becoming infinite. Its a common technique in Lisp. Maybe C programmers don't know that. Or maybe their compilers are too dumb to do RVO, aka, Return Value Optimization. Something akin to a ".tail" for that in its IR. (almost all virtual machines that are JIT compilers can do that, its kind of a trivial optimization)

  • @int32_

    @int32_

    7 ай бұрын

    @@monad_tcp it's not needed, but it can make your code prettier and less repetitive in some rare cases (the linux kernel often uses gotos for error paths)

  • @monad_tcp

    @monad_tcp

    7 ай бұрын

    @@int32_ yeah, that's a well know deficiency of the C language. that pattern is so used that compilers can actually do semantics analysis on it and I'm going to even admit that its the only valid use for goto. besides jumping to another case in a switch which is a neat misuse of goto that does work and very little people know you can actually do that.

  • @vitalyl1327

    @vitalyl1327

    6 ай бұрын

    Impossible. Goto is essential for representing irreducible CFG (for all procedural constructs are, by definition, reducible). Which means, pretty much any mildly complicated FSM, including all kinds of parsing and tree walking. Languages without a goto are crippled languages.

  • @vitalyl1327

    @vitalyl1327

    6 ай бұрын

    @@monad_tcp lol, now try to implement an efficient indirect threaded code interpreter without a goto.

  • @drkspace
    @drkspace7 ай бұрын

    Another good use case is if you're in a nested for loop and one of your inner loops needs to break out of the entire thing, instead of having a bool that propogates breaks up the loops, you can just have a goto that leaves the entire structure. I'm not sure, in c++, if this'll work with scoped variables, so that might be a case where you don't want to do it.

  • @ChapmanWorldOnTube

    @ChapmanWorldOnTube

    7 ай бұрын

    In this case, why would you not move all of those nested loops to their own function and simply return from it when you need to break all of the loops?

  • @WindLighter

    @WindLighter

    7 ай бұрын

    @@ChapmanWorldOnTube there might be a necessity to use a bunch pf local variables withion the structure, so you will need either to use global variables instead, that makes bug probability higher, or put all those stuff as a parameters into a function that is called from a single place of your code and depending on compiler that may cost you some perfomance and memory. Also the function will be stored at a different place in your code so you will actually need to spend extra attention to keep track of what is going on, so in this case a simple jump to a lable makes code actually cleaner and better in both readability and perfomance

  • @ChapmanWorldOnTube

    @ChapmanWorldOnTube

    7 ай бұрын

    @@WindLighter I of course don't share the same coding style or habits that you do, and I also don't code in C typically, so I hope you won't read it as confrontational that I disagree... Of course any call to a procedure/function is a performance concern, however, IMO making function calls is far more unfairly demonized than go-to. Function calling is a performance hit of a few milliseconds, which of course matters if called repeatedly in a loop - but presumably moving all of the nested loops within the isolated function means you need call it only once to initiate it - or at most, once per cycle of an outer-most loop. In terms of readability - yes, when reading the calling code you might have to go locate the function elsewhere in the source code - a small chore should you need to. However, if the function is well named, in many cases you may be able to read past it without being concerned. In addition, I find locating and reading separate functions to be far easier than the alternative - one long sprawling list of nested loops gives me shudders. I envisage functions growing to many pages (and have worked on such code bases), and would very much prefer to have to go find a function, rule it out in terms of relevance, and return to the calling function to continue reading. Parameter passing - If there are many local variables to pass then this could increase that function call overhead a little, but it also indicates a possible design flaw. Could the state information be wrapped up in a struct, which could be passed by reference? This isn't a cop-out, saying just pass a struct, but rather, all of those local variables must be logically relevant to each other (in abstract terms) to be required in the nested loops, and therefore could be conceptually combined into a struct representing the computational state, and with a suitable name to reflect what that is. From this the very concept of OOP falls forth. Ultimately, goto is an individual choice or preference, but I feel if you're going to use it, it should always be a prompt to reconsider, is your abstraction of the problem a good abstraction.

  • @anon_y_mousse

    @anon_y_mousse

    7 ай бұрын

    @@ChapmanWorldOnTube The problem with that solution is that you then must unpack the variables from the struct. Whether they're passed on the stack, and thus take up valuable stack space, or passed by address while contained in a struct, it either requires extra space to be used up or extra syntax to be had. Both solutions are less easily understood at a glance, more difficult to type in, and potentially fraught with extra bugs, on top of requiring extra copying of values which in a long-running loop will add up. Now, if the compiler optimizes said functions because you label them static and use -O3, you still have harder to grok code with more potential for bugs.

  • @ChapmanWorldOnTube

    @ChapmanWorldOnTube

    7 ай бұрын

    @@anon_y_mousse We are clearly coming from very different places. I think I hold the opposite position on every point that you made. I don't code C anyways, I have never really liked the syntax. I have always been more in the Writhian camp. I will bow out on a mutual disagreement on this one.

  • @emmiasilk9059
    @emmiasilk90597 ай бұрын

    Interesting. For the example you used as a good usage for a GOTO, I think the step-of-error-handling functionality *could* be reproduced using a switch statement instead (by passing in a value representing which step you are on, and letting that decide the starting point). But I think then use of a goto would make it more readable. Still, I can't help but wonder if there's an even more elegant way of dealing with this kind of circumstance.

  • @anon_y_mousse

    @anon_y_mousse

    7 ай бұрын

    In this instance, while I love C and I still think it's the best language, C++ actually provides a more elegant solution whereby the cleanup code goes into the destructor for a class so that if any part fails you could simply return from the function and the appropriate cleanup would occur. Even though I borderline hate Zig for the syntax choices they've made, I'll admit that defer is also a rather nice option and slightly more flexible.

  • @bbq1423

    @bbq1423

    7 ай бұрын

    In more recent languages there is defer and sometimes errdefer which does essentially the same thing. In languages with lambdas and destructors you can synthesize defer by creating a type with a constructor that takes a lambda and a destructor that runs the lambda.

  • @hellNo116
    @hellNo1165 ай бұрын

    the way i have experienced is that we tell it to newbies because newbies don't know how to write code and we don't want them to use it because they will be confused and write worse code. i have seen this live many times, while helping in uni.

  • @abuk95
    @abuk957 ай бұрын

    I did exactly this for my college project, because using early returns seemed more messy. I realized that 'goto' is not some forbidden practice and this is a valid use-case. Like with breaking out from an inner loop. Is this a normal practice to do with C in a professional environment?

  • @thefafala

    @thefafala

    7 ай бұрын

    It depends. But in embedded C, it's standard practice to use goto (as far as Ive seen)

  • @davesherman74
    @davesherman743 ай бұрын

    Grew up typing in BASIC programs on my Commodore 64, and GOTO was very common. When I learned C in college, the course didn't even mention the keyword goto. It was years later that I learned that goto was recognized in C. I can say the ONLY time I ever used goto in C was when I was trying to debug something and used it to skip over a section of code.

  • @acf2802
    @acf2802Ай бұрын

    Some asshole wrote a paper titled "goto considered harmful" and 56 years later idiots are misinterpreting it having only every heard the title and not the body and taking it as a universal law completely removed from it's original context. The paper was written in a time where FUNCTIONS were considered some confusing new-fangled invention by many programmers. The goal of the paper was to convince people that you should use higher level abstractions like functions. If you as a programmer in 2024 use functions (YOU DO) then you can COMPLETELY DISREGUARD "GOTO considered harmful" because IT'S NOT FOR YOU!

  • @DinHamburg

    @DinHamburg

    Ай бұрын

    back in the day FORTAN was widely used - and it had 'computed goto' and 'arithmetic if' which could easily create messy code which is nowadays completey inconceivable

  • @mattias3668
    @mattias36686 ай бұрын

    2:33: No, you print first so you are sure errno is not modified. Now, in this case there is no reason that errno would be modified, but that's not always the case.

  • @m.projects
    @m.projects7 ай бұрын

    retval could have been set to -1 at startup instead of before every goto statement 🤓

  • @robertgaines-tulsa
    @robertgaines-tulsa14 күн бұрын

    I remember our high school computer programming teacher in the mid to late 90s didn't even want us talking about the goto statement. It was a bit of a joke. Growing up in the 80s, home computers like the Color Computer just didn't have the fancy loops and structures of while or case. Except for for/next, we only had goto for jumps.

  • @kvk812
    @kvk81220 күн бұрын

    I remember using goto for my programs and my uni professor being not happy about it lmao. she made sure not to teach about goto statements even though i thought they were so op! but ig she was worried people are gonna get lazy and just use goto statements instead of properly understanding and implementing loops XD

  • @Bob-1802
    @Bob-18027 ай бұрын

    'break' and 'continue' are some kind of 'goto' in disguise.

  • @eagold
    @eagold4 ай бұрын

    sometimes, based on some expression in the nested loop, you need to break nested and parent loop i still don't know how to do that without goto

  • @speed488
    @speed4884 ай бұрын

    I'm working with an SDK of a transaction processing system which uses callbacks to send events. The callback function is essentially a big switch/case statement processing the event the SDK sends. There's one case where I need to process a failed transaction which is executing a function and closing the transaction exactly as the successful case. I've been contemplating using a goto there for maintainability. There's a strong chance the successful transaction case will change in the future and might not get updated the same way in the failure case; the goto would make sure the code is only written once. However, using a goto in a switch/case is quite an anti-pattern.

  • @futuremapper_
    @futuremapper_Ай бұрын

    I usually only use goto in command line apps where I need to validate inputs. Invalid input? Move back to the line that takes the input. Super simple and readable

  • @sorcdk2880
    @sorcdk28806 ай бұрын

    I would probably go with nested inversed if statements in a case like this, where instead of a cleanup on failure, you get a choice of continuation or local cleanup, which is then followed by the cleanup. Kind of like this: errors = 0 do buffer thing if (buffer succeeds) { do socket thing if (socket suceeds) { do socket use } else { perror("sucket") errors++ } close(socket) } else { perror("buffer") errors++ } free(buffer) return 0-errors

  • @mrbutish
    @mrbutishАй бұрын

    Goto is a must to make code readable, although it hurts readability when used improperly.

  • @jongeduard
    @jongeduard4 ай бұрын

    I fully agree! This is great code. I do not write C too often, but I have been correcting some of my own code similarly to this. Albeit with a break statement in my case. The point is to not write any more resource deallocation lines than allocation lines, as a good practice. In order not to accidentally leak resources or create duplicate frees. As soon as you allocate stuff, you do not want to diverge. All code paths should come together at the end of your code. It's good te remember that C is a low level language and does not have any try finally constructs or RAII features. And there's no GC. It's not a functional programming language where you can always do lots of return statements without any worries.

  • @DeathStocker
    @DeathStocker7 ай бұрын

    Another good use case of gotos is in computed gotos for dynamic dispatch. IIRC a simulator used to use this for their opcode dispatch. I don't know if modern compilers don't need this and can optimize it automatically but I remember it being claimed to be 20% faster

  • @bbq1423

    @bbq1423

    7 ай бұрын

    This is still the case afaik. That thing is using a computed goto, which is not standard, but actually really cool. Reason for it being faster was something along the lines of optimizers optimizing switches inside of loops to small code rather than the longer code with more branches. In this case you'd want many branch sites for the opcodes since the cpu is able to predict the behavior of the opcode code better than a single branch site.

  • @meoDomicio
    @meoDomicio7 ай бұрын

    I love the configuration of your vim editor

  • @bobobo1673
    @bobobo16737 ай бұрын

    A teacher told me that if I used "goto", he would make me fail all the exams I took where I used "goto" and that that sentence should never be used

  • @SaSo-mk6yh
    @SaSo-mk6yh6 ай бұрын

    My teacher always got visibly upset when anyone used gotos 😂

  • @mk72v2oq
    @mk72v2oq7 ай бұрын

    Bad example to be honest. This case can easily be substituted by simply nesting the code. Or, if you don't like deep nesting, by function calls. I.e. int proceed_with_sfd(int fd, void *filebuf, int sfd) { // Do stuff with fd, filebuf and sfd return 0; } int proceed_with_filebuf(int fd, void *filebuf) { int sfd = socket(...); if (sfd == -1) return -1; int retval = proceed_with_sfd(fd, filebuf, sfd); close(sfd); return retval; } int proceed_with_fd(int fd) { void *filebuf = malloc(...); if (filebuf == NULL) return -1; int retval = proceed_with_filebuf(fd, filebuf); free(filebuf); return retval; } int main() { int fd = open(...); if (fd == -1) return -1; int retval = proceed_with_fd(fd); close(fd); return retval; }

  • @malcolmgruber8165

    @malcolmgruber8165

    7 ай бұрын

    But why risk the cache miss with a function call when GoTo achieves the same thing without the issue.

  • @mk72v2oq

    @mk72v2oq

    7 ай бұрын

    @@malcolmgruber8165 because this is 1000 times more readable and easier to debug. Following your logic lets write all the code in 1 giant function with goto jumps. Not to mention that such small functions will be inlined by the compiler anyway. So that kind of premature optimization quickly becames pointless.

  • @jbird4478

    @jbird4478

    7 ай бұрын

    @@mk72v2oq Honestly, I find this a lot less readable. Now you have 4 functions for a trivial thing, and if you do this with all functions, you end up with a heck of a lot functions, all of which require a sensible and unique name. To follow the control flow I now have to scroll upwards and scan function names, which are going to get progressively worse the more you apply this, and keep track of what each argument actually is. It requires more code that you not only have to write, but also have to parse when reading it. And either way, you just have a single linear control flow with multiple entries to a single linear flow on failure. Except that in this case, both linear flows are scattered in the code.

  • @mk72v2oq

    @mk72v2oq

    7 ай бұрын

    @@jbird4478 well, it is the nature of C. In practice you usually can do it smarter and shorter though. The main goal here is to restrict area of responsibility of every function. The problem with goto that it can be misused very easily. It is even more dangerous than regular unsafe C things. But yeah, the language itself is inherently flawed in this regard. C is the last one where goto is even thinkable (if you don't still code in BASIC lol). Embrace modern languages if you can. Functional elements make it way more clean. Also, when control flow has conditional branches, it is not linear by definition.

  • @jbird4478

    @jbird4478

    7 ай бұрын

    @@mk72v2oq Any programming construct can be misused. It's the nature of C that you can use goto for such situations. And any paradigm can be over implemented. Limiting the responsibility of functions is generally a good idea, but it can certainly be overdone. To open a file, in practice one often has to do a few things more than just calling open(), but that doesn't necessarily mean they all have be separate functions. It can be practical to keep a reasonable amount of things in a single function. And you're right of course. I should've put "linear" in quotation marks or something, because what I meant is that if all goes well there's really only one code path. And if you're reading it, that's generally what you want to know first. Then the points of failure are things you follow if needed, but in case that's also just a single path. So regardless of how you write it, what happens here is the code runs from A-Z, except it jumps out on failure. And that's precisely what the version with gotos reflect in the code. Higher languages provide other alternatives for this, like exceptions or scoped destructors, but C doesn't. C provides its own tools, and one of them is goto. Like all tools, there are situations to use it, and situations where you should not, but there's no reason to avoid it at all costs like some people seem to think.

  • @eltreum1
    @eltreum15 ай бұрын

    We have it so good and rough these days. IF and GOTO were the only flow controls we had. There was no malloc or garbage collection. We had to remember the addresses of the ROM and RAM usable memory registers and read/write them directly with PEEK and POKE. You could make a sheet of graph paper into a chart and memory map the entire program and map the execution flow end to end before typing anything if you wanted. What's old is new I guess. We started with strict typed languages and mainframes, then we wanted dynamically typed user-friendly languages and our own servers in the enterprise, now we are back on the strict typed language kick and cloud computing as a modern replacement for the mainframe.

  • @Songfugel
    @Songfugel29 күн бұрын

    You can use composite functionality to achieve the exact same thing as here without gotos, however, where gotos shine, is making specific jumps out from multilevel iterators (like nested loops) that can get very messy and have to do extra steps without them edit: meh, only now noticed this was and old video and others had already commented the same thing

  • @TrOllOchamO
    @TrOllOchamO7 ай бұрын

    Just pointing out a little error in the first version of the error handling code. You should call perror first before calling any function that could set errno. In this case the error message won't be very helpful since it will print the termination message of the close function instead of the malloc error. Great video 😁

  • @lunlunnnnn

    @lunlunnnnn

    7 ай бұрын

    Not like it really matters, the point of the examples was to demonstrate a good usage of goto, not to show perfect code

  • @marcingardyjan6680
    @marcingardyjan66806 ай бұрын

    In C# your example would be: using (open file) { do something } that's all. If "do something" fails it will close object that was created in using section - in this example close a file. Also similar think you can make with try catch section. You can use functions with return. Also using break and continue. The only reason to use goto is when you want break from double loop. (Loop in a look). Break will exit from one loop only.

  • @apollolux
    @apollolux6 ай бұрын

    I’ve never seen goto/raw jumps as illegal in whatever language I was using that had them, I just considered the results of their usage to be more _potentially_ uncontrollable or unpredictable and therefore requiring more discipline, foresight/planning, and intention in code than “standard” conditional logic conventions.

  • @stapler942
    @stapler9427 ай бұрын

    One thing I still find hilarious is that Java has goto as a reserved keyword just so nobody can use it. 😆

  • @xwtek3505

    @xwtek3505

    2 ай бұрын

    I heard that goto keyword is used internally in javac

  • @sub-harmonik

    @sub-harmonik

    Ай бұрын

    but it's true that the labelled-block-break mechanism of java can almost always do the same thing, and sometimes it's clearer to have the 'section that can be jumped out of' in a block like that.

  • @mb00001
    @mb000017 ай бұрын

    i kind of predicted what you were going to do only i was thinking of a switch statement, which in retrospect won't work because the jumps are for different conditions

  • @JackBond1234
    @JackBond123423 күн бұрын

    Just make 3 cleanup functions that each call the next step below, if there is one, so if you fail early, you shortcut the stack, but if you fail late, you call the whole stack

  • @realdragon
    @realdragon6 ай бұрын

    So basically if you have 1 list to go through in functions but each function starts at different point then you use go to. When function_1 starts on top of the list and goes trough every element but function_2 starts in the middle of the list we don't want to copy paste half of the list, we just say program to go to that half point of list we defined defined only once

  • @garypinkett6275
    @garypinkett62756 ай бұрын

    Even though it goes against everything I thought I believed in… I love this

  • @MikeM8891
    @MikeM88917 ай бұрын

    I started programming in TI basic and got accustomed to using 'goto's just to realize that they are either not in or frowned upon in other languages. The irony is that asm is full of 'goto's in the form of 'jmp'.

  • @roadrunner3563
    @roadrunner35637 ай бұрын

    depends on how well the language handles error conditions. sometimes there's no better way.

  • @tjdewolff5104
    @tjdewolff51045 ай бұрын

    The proper answer to this code chaos is (hold on tight): nest your code. Yes, you read that correctly: nest your code! You started of quite nicely by introducing a return variable. This should ALWAYS be the very first declared variable in your code and set to THE error code, here -1. On success, the inner level of nesting, set it to 0. This saves a whole lot of lines assigning -1 to the error code variable. Furthermore nesting provides a perfect way to achieve congruency between scope and lifetime of a variable. Actually it's the only way.

  • @BobFrTube
    @BobFrTube7 ай бұрын

    The point I made a half century OK, (OK, more than) is that you want to reading the static state of the code to give you an understanding of the dynamic state. Unrestrained gotos make this difficult. This is why we use words like "try/finally", "break", "continue" etc. to indicate that are doing constrained flows and thus our reading of the static code is consistent with the dynamic flow. If you're using an ancient language and need to use GOTO, then annotate the usage to give the reader (and yourself) and even break (pun?) in understanding what is going on.

  • @AterNyctos
    @AterNyctos7 ай бұрын

    That last case you mentioned (the good use of a goto) feels like a switch statement in a way. I supposed as most languages I use don't have goto, I'd increment or set a numeric variable and then switch() it for error handling. Great video! I learned a lot :)

  • @gregorymorse8423

    @gregorymorse8423

    7 ай бұрын

    Interestingly with a switch in a loop or loop in a switch, break and continue operate differently.

  • @AterNyctos

    @AterNyctos

    7 ай бұрын

    @@gregorymorse8423 Huh, didn't know that. Cheers!

  • @gregorymorse8423

    @gregorymorse8423

    7 ай бұрын

    @@AterNyctos yes break in switch always breaks the switch. But continue in a switch effects the loop. Weird aspect of C syntax

  • @gregorymorse8423

    @gregorymorse8423

    6 ай бұрын

    @@JodyBruchon you obviously are extremely ignorant. Switch statements are jump tables except for ones with only 2 or maybe 3 branches. You literally have no idea of how modern processors and compilers work. You've given serious evidence.

  • @gregorymorse8423

    @gregorymorse8423

    6 ай бұрын

    @JodyBruchon maybe I'm being a bit harsh but seriously Wikipedia "branch table". Practically speaking this knowledge is important though with a good compiler perhaps it needn't be.

  • @Wyvernnnn
    @Wyvernnnn24 күн бұрын

    Since using RAII and Result types I haven't used a single goto to cleanup or do error returns.

  • @SegFaultMatt
    @SegFaultMatt6 ай бұрын

    It’s nice to have “finally” in higher level languages 😅

  • @EdwardChan.999
    @EdwardChan.9997 ай бұрын

    So goto is like the fall-through feature in switch..case, right? Upper cases does something that the lower cases don't, while also reusing the code of the lower cases.

  • @xorxpert
    @xorxpert6 ай бұрын

    personally for me, i would have a single dispose function that checks if objects aren’t null pointers, and properly free them then return appropriate value.

  • @MatVeiQaaa
    @MatVeiQaaa6 ай бұрын

    why is goto bad: it makes your code look more like assembly, and the whole point of programming languages is to not use assembly.

  • @lordsmeagol3390

    @lordsmeagol3390

    19 күн бұрын

    If you must use goto (usually to do something the language doesn't support, like breaking out of nested loops), use it sparingly and make it as clear as possible what it is doing, by using descriptive label names.

  • @KneeCapThief
    @KneeCapThief6 ай бұрын

    What about using gotos to break out of multiple loops without annoying if statements and variables

  • @LT_Cubing
    @LT_Cubing10 күн бұрын

    Haha. I should check some of my old code, because I know I’ve definitely used it a few times in the past. Just resort to the void functions now.😊

  • @hexadecimalpickle
    @hexadecimalpickle7 ай бұрын

    goto statements are a powerful advanced tool. They should not be used by inexperienced developers simply because they're all too easy to abuse and make an habit of it, which is what used to happen long time ago - hence the stigma. But like anything else, goto statements should be encouraged whenever they are the best tool for the job.

  • @ChrisM541

    @ChrisM541

    7 ай бұрын

    Every expert-level assembly games programmer of the 70's-90's (and there was a lot) would agree.

  • @stera182
    @stera1824 ай бұрын

    Another use of goto is to escape nested loops nicely.

  • @mage3690
    @mage36906 ай бұрын

    I've only ever used goto in C where I would've used "break 2;" (or any larger number) in PHP. Honestly, I'm 50/50 on which is more readable: "break ;" is more readable in an immediate sense, but "goto breaknum;" is more readable when you want to figure out where things are going, especially if there's a complex nesting going on. Either way, it's better than the JS version, which makes you put the label _above_ the scope, then "break label;": i.e. "forlabel: for () { if () { break forlabel; } }" I get it, you're labeling the scope and then breaking from that scope, but it's still the worst of all worlds.

  • @fakestiv
    @fakestiv6 ай бұрын

    This is the reason why zig's "defer" is a great.

  • @TheJaguar1983
    @TheJaguar19836 ай бұрын

    I would probably nest these in inlined functions instead of using GOTO. Though, that could get rather cumbersome if you have a lot of things to close or free. I think the no GOTO thing is due to overuse and/or interfering with higher level language elements like unwinding and reference counting.

  • @MrEthanhines
    @MrEthanhines4 ай бұрын

    In the 80’s I programmed in Basic for the C64 and there were *tons* of Gotos hence why i found it strange why they have fallen out of favor.

  • @richardfarrer5616
    @richardfarrer56165 ай бұрын

    So, since you mention switch (evil grin). retval = 0; if(error1) { retval = 1; goto oops; } dostuff1(); if(error2) { retval = 2; goto oops; } dostuff2(); ... if(errorn) { retval = n; goto oops; } dostuffn(); do_more_stuff(); oops: switch(retval) { case n: tidyn(); case n-1: tidyn_1() ... case 1: tidy1(); case 0: return retval; } What could be clearer than (ab)using the fallthrough mechanic?

  • @emmettdja
    @emmettdja5 ай бұрын

    I use goto whenever I have user input validation. Imo it is cleaner than using a while loop to ask the user to re-enter their input.

  • @rhone733
    @rhone7337 ай бұрын

    Gotos are fine when used properly. I only use them inside of functions to jump to a cleanup or error case.

  • @vibaj16

    @vibaj16

    29 күн бұрын

    The main use I have for goto is breaking out of nested loops. Yes, it's possible to do it without goto, but most methods for that make the code less readable to me. People only really do that for the sake of not using goto.

  • @assimilater-quicktips
    @assimilater-quicktips6 ай бұрын

    The biggest problem to my knowledge with goto is the potential to mess up the stack. It’s generally just safer to build off the stack with a series of function calls than create a state where the call stack is uncertain

Келесі