wanna get good at programming? check out lowlevel.academy and use code THREADS20 for 20% off lifetime access. or dont. im not a cop
@pepsitoly10 ай бұрын
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_maison919310 ай бұрын
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.
@kameronbriggs2353 ай бұрын
There are loops which are impossible without goto.
@AstroTibs3 ай бұрын
"GOTOs make your code unreadable, therefore code without GOTOs is readable" is the "denying the antecedent" fallacy.
@DerPinguim3 ай бұрын
Also annoyed me a bit
@james-m-82857 күн бұрын
Nobody accused him of being educated
@jimnoeth304010 ай бұрын
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.
@elpatosilva10 ай бұрын
Edsger Dijkstra probably hates you. Just like BASIC
@anon_y_mousse10 ай бұрын
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_mousse9 ай бұрын
@@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_mousse9 ай бұрын
@@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.
@1sthaloman9 ай бұрын
@@anon_y_mousse restart?
@ChunGzter10 ай бұрын
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.
@talkysassis10 ай бұрын
This can lead to some ugly bugs by getting the file pointer on another scope
@GuentherJongeling-hu6oe10 ай бұрын
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)
@lMINERl10 ай бұрын
@@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.
@TheRobbix120610 ай бұрын
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_tang10 ай бұрын
but with a function you can't break, continue, or return from the function that it was called from
@ishi_nomi10 ай бұрын
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.
@georgerogers116610 ай бұрын
Or exiting a loop in a switch.
@nolanfaught697410 ай бұрын
Their use is recommended in the kernel to support a “centralized control flow” method of coding
@monad_tcp10 ай бұрын
Its because normal control flow is lacking in the C language. Something like "try/finally" , I don't know.
@jbird447810 ай бұрын
@@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_tcp10 ай бұрын
@@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.
@deedoubs9 ай бұрын
Goto is fine, just don't go up.
@MrAB-fo7zk4 ай бұрын
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.
@deedoubs4 ай бұрын
@@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-fo7zk4 ай бұрын
@@deedoubs you're right, I meant to say just "usually" for an error condition, not always or that it must be for that purpose!
@jnharton3 ай бұрын
The important thing is to maintain a consistent, traceable flow of execution. You can make a real mess of spaghetti code using goto.
@jnharton3 ай бұрын
@@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
@kuhluhOG10 ай бұрын
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?").
@Optimus61286 ай бұрын
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.
@xwtek35054 ай бұрын
I can't imagine how the code snippet should do other than undefined behavior
@kuhluhOG4 ай бұрын
@@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
@Stratelier4 ай бұрын
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.
@oddcraft184 ай бұрын
Bro u need goto ur gonna miss out on 0.1us
@Trekiros10 ай бұрын
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.
@drachefly8 ай бұрын
couldn't you have used a labeled break?
@xeridea7 ай бұрын
@@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.
@amigalemming4 ай бұрын
@@drachefly or put the loop in an extra function and leave both the loop and the function with a 'return'.
@drachefly4 ай бұрын
@@amigalemming That'd work too!
@simongido5653 ай бұрын
@@amigalemming Exactly what I had in mind.
@metal57110 ай бұрын
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.
@IBelieveInCode10 ай бұрын
Agreed.
@niewazneniewazne189010 ай бұрын
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;
@gustavoholo100710 ай бұрын
Did you study electrical engineering metal? I didn't expect you here I like your videos
@monad_tcp10 ай бұрын
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.
@soniablanche56725 күн бұрын
yeah c++ has destructor and unique pointers so you don't need to use the goto clean up pattern
@acf28024 ай бұрын
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!
@DinHamburg4 ай бұрын
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
@oglothenerd10 ай бұрын
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.
@kevinyonan966610 ай бұрын
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
@shadamethyst125810 ай бұрын
@@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.
@TheSast10 ай бұрын
Agreed, can't live without them.
@oglothenerd10 ай бұрын
@@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-vu8fm5vb4n10 ай бұрын
@@kevinyonan9666you are FORCED to handle the errors or else the compiler refuses to compile your code.
@LogicEu10 ай бұрын
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.
@lukekurlandski765310 ай бұрын
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.
@sivorano10 ай бұрын
@@lukekurlandski7653I think you also need either goto or recursion for turing completness.
@LogicEu10 ай бұрын
@@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.
@roberthickman409210 ай бұрын
Its stupid that wasm was designed without a jump.
@Zooiest10 ай бұрын
@@roberthickman4092 br and br_if
@larjunmnath10 ай бұрын
Man you are the sole reason why I fell in love with assembly, couldn't thank you more.
@4115steve10 ай бұрын
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
@Zullfix10 ай бұрын
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.
@kuba4ful7 ай бұрын
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.
@captmcneil3 ай бұрын
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_Meeo10 ай бұрын
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: ...
@dontthrow606410 ай бұрын
Nice concept. Like when you have a piece of puzzle that almost fits and then you find the real piece.
@LittleRainGames9 ай бұрын
Oh wow, didnt know that about for loops. Great to know
@PalladinPoker8 ай бұрын
you could also do the following and skip using goto, although goto is cool. uint16_t i = 0; while (i < loop_range && !(some condition)) { SomeFunction(i); } //destroy i
@Minty_Meeo8 ай бұрын
@@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.
@gayusschwulius84908 ай бұрын
@@PalladinPoker That's WAY more inefficient due to the additional call and check, even more so if the outside function isn't inlined.
@captainfordo110 ай бұрын
Another use of goto is for breaking out of a nested loop.
@ThePCxbox9 ай бұрын
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
@Rock48966 ай бұрын
Especially for text adventures
@BlitterObject10 ай бұрын
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.
@franciscofarias638510 ай бұрын
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".
@loc472510 ай бұрын
*"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.
@anon196310 ай бұрын
@@loc4725if you give anyone a gun* there
@jbird447810 ай бұрын
@@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.
@loc472510 ай бұрын
@@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.
@shadowchasernql9 ай бұрын
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.
@NYKevin1007 ай бұрын
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.
@valseedian7 ай бұрын
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.
@xwtek35054 ай бұрын
Is there a language that allows goto to a label in different function scope?
@valseedian4 ай бұрын
@@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
@valseedian4 ай бұрын
@@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.
@sinom10 ай бұрын
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.)
@pheww8110 ай бұрын
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.
@BrotherCheng10 ай бұрын
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.
@Anubis110110 ай бұрын
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.
@marshallscarpulla30329 ай бұрын
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.
@iWhacko9 ай бұрын
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.
@marshallscarpulla30329 ай бұрын
@@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.
@gloowacz7 ай бұрын
@@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.
@jordixboy10 ай бұрын
If, while, for, underneath they are just "gotos"
@fders93810 ай бұрын
@@Proferk Hey, that's why C is just a macro assembler, right?
@aquapendulum3 ай бұрын
@@Proferk Any code we write that isn't 0s and 1s is just syntactic sugar for 0s and 1s!
@CallousCoder9 ай бұрын
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.
@gregorymorse84239 ай бұрын
Maintainability of code isn't an academic discussion. I'm sure everyone at your work place loves your spaghetti code lol
@CallousCoder9 ай бұрын
@@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.
@leightonmitchell256410 ай бұрын
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.
@georgehelyar10 ай бұрын
Another way to do this would just be to put it in a function and return out
@CottidaeSEA10 ай бұрын
@@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.
@js4664410 ай бұрын
@@CottidaeSEAwhy would an additional function necessarily be part of the interface?
@CottidaeSEA10 ай бұрын
@@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.
@keris392010 ай бұрын
@@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.
@spudbencer71797 ай бұрын
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.
@jbird447810 ай бұрын
This is basically the goto solution (pun intented) for handling errors in the Linux kernel.
@vodkacannon3 ай бұрын
That’s some very encoded humor.
@MarioDanielCarugno10 ай бұрын
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_tcp10 ай бұрын
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...
@Bob-180210 ай бұрын
'break' and 'continue' are some kind of 'goto' in disguise.
@alexandreparent394210 ай бұрын
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.
@TheRobbix120610 ай бұрын
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-harmonik4 ай бұрын
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)
@CottidaeSEA10 ай бұрын
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.
@xeridea7 ай бұрын
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.
@SolidFake9 ай бұрын
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).
@LeonAlkoholik6710 ай бұрын
I'm gonna goto hell now
@SegFaultMatt9 ай бұрын
It’s nice to have “finally” in higher level languages 😅
@tjdewolff51048 ай бұрын
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.
@ihaytejews6 күн бұрын
really cool feature of C. thanks for sharing.
@sorcdk28808 ай бұрын
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
@drkspace10 ай бұрын
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.
@ChapmanWorldOnTube10 ай бұрын
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?
@WindLighter10 ай бұрын
@@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
@ChapmanWorldOnTube10 ай бұрын
@@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_mousse10 ай бұрын
@@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.
@ChapmanWorldOnTube10 ай бұрын
@@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.
@thebuffman559710 ай бұрын
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.
@lycanthoss10 ай бұрын
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.
@thebuffman559710 ай бұрын
@@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.
@insomnyawolf9 ай бұрын
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
@spearmintlatios90479 ай бұрын
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.
@mage36909 ай бұрын
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.
@MatVeiQaaa9 ай бұрын
why is goto bad: it makes your code look more like assembly, and the whole point of programming languages is to not use assembly.
@Lord-Sméagol3 ай бұрын
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.
@mk72v2oq10 ай бұрын
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; }
@malcolmgruber816510 ай бұрын
But why risk the cache miss with a function call when GoTo achieves the same thing without the issue.
@mk72v2oq10 ай бұрын
@@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.
@jbird447810 ай бұрын
@@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.
@mk72v2oq10 ай бұрын
@@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.
@jbird447810 ай бұрын
@@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.
@hexadecimalpickle10 ай бұрын
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.
@ChrisM54110 ай бұрын
Every expert-level assembly games programmer of the 70's-90's (and there was a lot) would agree.
@ProjSHiNKiROU10 ай бұрын
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_tcp10 ай бұрын
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_10 ай бұрын
@@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_tcp10 ай бұрын
@@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.
@vitalyl13279 ай бұрын
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.
@vitalyl13279 ай бұрын
@@monad_tcp lol, now try to implement an efficient indirect threaded code interpreter without a goto.
@SaSo-mk6yh9 ай бұрын
My teacher always got visibly upset when anyone used gotos 😂
@mrbutish4 ай бұрын
Goto is a must to make code readable, although it hurts readability when used improperly.
@apresthus8710 ай бұрын
This is the first time i've ever I just instantly went and bought a course from a KZfaqr 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! :)
@AidenElliott-ff2vt8 ай бұрын
Goto is also very useful for breaking nested loops.
@H3liosphan10 ай бұрын
Oh god no. I disagree - what's wrong with putting all those error handling bits into a single function and calling that? You literally just pass in a different error descriptor at each instance. If you want to go the extra mile u can even tell the error function to close whatever handles u have open too. I started in Basic and didn't traditionally have functions , so I grew up learning programming with Goto, but I have seen the light. There is nowhere a goto beats a function.
@stapler94210 ай бұрын
One thing I still find hilarious is that Java has goto as a reserved keyword just so nobody can use it. 😆
@xwtek35054 ай бұрын
I heard that goto keyword is used internally in javac
@sub-harmonik4 ай бұрын
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.
@hyper_lynx4 ай бұрын
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
@emmiasilk905910 ай бұрын
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_mousse10 ай бұрын
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.
@bbq142310 ай бұрын
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.
@mattias36689 ай бұрын
<a href="#" class="seekto" data-time="153">2:33</a>: 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.
@_a_x_s_5 күн бұрын
When I use goto, it’s only used for the resource cleanup and error code return when something wrong happens in the middle of the function. It really helps me keep away from nested and duplicated code. I can’t think of any other good usage of the goto keyword.
@futuremapper_4 ай бұрын
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
@justSalty6 күн бұрын
This video ends with a valid use case for goto, but I think it could be better. If you follow structured programming, the compiler will handle all of the jumping for you and it would be both a. much more readable and b. much more maintainable. b. By following structured programming, the function prevents updates to parts of it that will not affect/break other portions of the function. a. By following structured programming, anyone who views the function can easily see at a glance the flow of the code without having to parse any statements at all, specifically the goto statements. Watch the lecture The Forgotten Art of Structured Programming by Kevlin Henney, it's a great talk and a must watch for all programmers.
@AlFasGD6 ай бұрын
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
@m.projects10 ай бұрын
retval could have been set to -1 at startup instead of before every goto statement 🤓
@JackBond12343 ай бұрын
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
@Songfugel3 ай бұрын
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
@jongeduard6 ай бұрын
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.
@jacmkno50193 ай бұрын
Finally someone illustrates how gotos can be acceptable in some situations. People gets blind with these things...
@D0Samp4 ай бұрын
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.
@TrOllOchamO10 ай бұрын
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 😁
@lunlunnnnn10 ай бұрын
Not like it really matters, the point of the examples was to demonstrate a good usage of goto, not to show perfect code
@nezbrun8724 күн бұрын
I've been writing C professionally for almost 40 years. I can very confidently state that I've never, ever found any need to use a goto. There are always better, more structured and readable ways of achieving this, including how to achieve the solution given in the video. I can't think of any "performance" reason to do it either: you certainly don't have any need to save a few nanoseconds in the example given.
@realdragon9 ай бұрын
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
@bobobo167310 ай бұрын
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
@BobFrTube10 ай бұрын
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.
@robertgaines-tulsa3 ай бұрын
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.
@rhone73310 ай бұрын
Gotos are fine when used properly. I only use them inside of functions to jump to a cleanup or error case.
@vibaj163 ай бұрын
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.
@cmyk89647 күн бұрын
Pre-emptive guess: Because humans make mistakes, and Gotos divorce syntax from the underlying logic, making mistakes more likely (e.g. accidentally reusing a Goto label, using the wrong label, reusing a variable from another part of the code)
@gsestream4 ай бұрын
try program in assembly without using JMP, even once, function call is only a JMP with an automatic paired return.
@videakias30007 ай бұрын
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)
@speed4886 ай бұрын
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.
@TheGrimravager7 ай бұрын
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.
@KneeCapThief8 ай бұрын
What about using gotos to break out of multiple loops without annoying if statements and variables
@the_srm4 ай бұрын
First, read „GoTo statement considered harmful“. Then, read „‚GoTo considered harmful‘ considered harmful“ 😊🎉
@mage36909 ай бұрын
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.
@marcingardyjan66809 ай бұрын
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.
@agsystems822010 ай бұрын
They are good for state machines in particular. Tail call functions are sort of better versions of them, and the difference is informative. Tail calls need to have context explicitly passed, while gotos retain the same context. This is why goto is so dangerous. When you read a block entered via goto you have no idea of what the context is (neither does the compiler), but responsibility for cleaning up the context is passed anyway! We often see weird loop contortions in an attempt to make things that are not loops fit into them, and it really bugs me. State machines are some of the worst offenders, but maps are often maps in a programmer's head, converted to a loop for the code, then converted back to a map by the compiler for vectorisation! Goto is a fantastic pattern for building a state machine where each state is working on the same context, such as parsers. Sure, the control flow is unpredictable, and 'spaghetti like', but sometimes this is inherent to the system you are modelling rather than bad code. Goto is a very crude tool, but most languages don't have better ones for non looping control flow. Tail calls are pretty close, but ideally you would want to avoid the function call overhead when you just want to build a state machine. I would like to see dedicated state machine control flow structures, more restricted than goto, but still able to handle non looping control flows elegantly without programmers having to translate it out of the form that it exists in their head.
@Zeero38463 ай бұрын
Could've initialized retval to -1 to save a line per error case. It also would've implied that you don't succeed until you do. Also, if you've ever read a reasonably complex Batch script in Windows/DOS, you'd know that gotos were the closest thing to functions unless you enabled extensions. Cascading goto error handling was also commonplace.
@AiOinc13 ай бұрын
"I'm already having trouble" Man, these programmers today...
@Stratelier10 ай бұрын
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.
@Hublium9 ай бұрын
It also specifically had the language feature "On Error GoTo ..." for the use case similar to the one shown in the video.
@Stratelier9 ай бұрын
@@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!
@Alibaba-id4dw10 ай бұрын
Quick way to check if the programming language you are about to learn is for babies or not: ask if the language supports goto.
@stera1826 ай бұрын
Another use of goto is to escape nested loops nicely.
@pitrex1113 ай бұрын
Congratulations you've invented c++ exception system in C
@anon-fz2bo10 ай бұрын
0x10 = 16 base 10 so why is there a subtract instruction in asm even tho there was no sub operation in the C source file? curious
@Lord-Sméagol3 ай бұрын
The SUB instruction is automatically generated by the compiler to reserve space on the stack for the function's local variables. PUSH RBP ; save current base pointer MOV RBP, RSP ; set base pointer to current stack pointer SUB RSP, 0x10 ; reserve 16 bytes space for local variables ; LEAVE ; this sets the stack pointer to the base pointer, which undoes the SUB RSP, 0x10 then it POPs the old base pointer from the stack RET ; return to caller
@kvk8123 ай бұрын
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
@Wyvernnnn3 ай бұрын
Since using RAII and Result types I haven't used a single goto to cleanup or do error returns.
@kennethvalbjoern3 ай бұрын
As a senior C#-developer I say, that this video so perfectly illustrates, why the C-language should be outlawed 😉 Do NOT learn C unless you do lowlevel hardware programming. Many other languages such as C# are much easier and more safe to use than C.
@zxuiji7 ай бұрын
you could further simplify that code with a macro: #define ERRTHENGOTO( RETVAL, LABEL, MSG ) { retval = RETVAL; perror(MSG); goto LABEL; } ... if ( cond ) ERRTHENGOTO( -1, cleanup_x, "failed y" ) Sure the lack of semicolon makes it look a bit wrong but the all caps name helps indicate it's a macro and shouldn't be worried about the look of it.
@dave0smeg3 ай бұрын
I've not done any programming since Spectrum BASIC. That thing was full of GOTO statements.
@davesherman746 ай бұрын
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.
@richardfarrer56168 ай бұрын
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?
@RavarYgamer2129 ай бұрын
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
@RGBHD4043 ай бұрын
Gotos aren't bad until you have to refactor a dogshit 2000+ lines function using multiple of them.
@powertomato7 ай бұрын
An exception in C++ is basically a goto chain. Everywhere, where throwing an exception in a higher language would be appropriate I consider a valid use of goto. Something resembling try-catch-finally would be an unreadable mess in C without goto
@abuk9510 ай бұрын
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?
@thefafala10 ай бұрын
It depends. But in embedded C, it's standard practice to use goto (as far as Ive seen)
@eagold6 ай бұрын
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
@hellNo1167 ай бұрын
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.