EEVblog® Electronics Community Forum
Products => Computers => Programming => Topic started by: metertech58761 on March 26, 2025, 04:11:55 pm
-
I have some assembly code I want to eventually rewrite into C, and I have isolated the four main loops (there's still an interrupt, but that comes later).
In these loops, there is some code where the operator is asked to press the Repeat key if they want to run the current test again or press the Next key to continue.
A typical instance:
suite3_11
JSR getKey
CMPA #$13 ; repeat
BNE suite3_12
BRA suite3 ; re-run current test
suite3_12
CMPA #$1B ; next
BNE suite3_11
; we now continue to the next step
So, how would I go about doing this?
-
Given:
JSR = function call
CMPA = if ( accumulator == '\x13' ) ...
BNE = else
BRA = goto
Rewrite as:
suite3:
suite3_11:
char ch = getKey();
if ( ch == '\x13' ) goto suite3;
suite3_12:
if ( ch != '\x1b' ) goto suite3_11;
...more next step code here...
But the above is too literal; make it more structured (less spaghetti) like:
void suite3() {
while(1) {
switch(getKey()) {
case '\x13': continue;
case '\x1b': break;
...more case code here...
default: continue;
}
...more next step code here...
break; // only once thru loop; used to avoid gotos.
}
}
Your assembly is a bit odd because BRA suite3 and BNE suite3_11 jumps to the same point unless there is test suite3_10 code prior to suite3_11. Maybe you intend to JSR getKey at the top of suite3 and then testing different keys results in exit, re-run, or different tests? Seems odd to have JSR getKey be specific to the suite3_11 test. Yes, this may seem more convoluted than the earlier code snip but you may see a theme develop and re-arrange further.
-
Here's the abbreviated code I'm looking to eventually rewrite:
The existing code writes to a display buffer that gets pushed into a 8279 display controller via calls to the dispRefresh routine. I want to replace all that with writes to an LCD.
As for the snippet I just showed, there are multiple instances of this throughout the process loops.
Basically, after a test or group is completed, the keypad is polled for a keypress (poll the 8279's EIRQ line, wait for a state change, then retrieve the matrix value - that code would also be replaced).
The code shown is a loop that you can only exit if you press Repeat (sending you back to a designated point) or Next (falling down to the next instruction).
I plan to replace the matrix value with flags for each of the function keys (Clear, Next, Repeat, Test, Enter). There's a sixth function key (Reset), but I'm debating if I want a soft or hard reset.
-
The following code should re-implement everything from suite3 on down. Please confirm as I've only compiled it; not tested.
It's not a simple pattern as there are some tests where repeat isn't from the first test or some tests jump to other tests without key checking.
I suggest you to print it out on paper and highlight the JSR getKey repeat key and next key check blocks.
Take note of which tests the repeat and next key-presses jump to.
int repeatFrom = 1; // assume repeat from first test unless otherwise changed
for(int test = 1; test <= 8; ) { // loop from first to last test
switch(test) {
case 1: test_61(); break; // DCT Analog 1 this test is always run upon entry to the loop before key check
case 2: test_62(); break; // DCT Analog 2
case 3: test_63(); break; // DCT Analog 3
case 4: test_64(); break; // DCT Analog 4
case 5: if (optbyte & 0x02) {
test_70(); // download data from DCT
test_71(); // send message to DCT
test_72(); // strobe DCT relays
repeatFrom = 5;
test++; //skip over 6
} else {
test_75(); // get dctdata1 value from UUT
test = 6; // jump to specific test
continue; // don't test for keypress
}
break;
case 6: test_76(); // DCT relay tests
repeatFrom = 6;
break;
case 7: test_73(); // write data back to DCT (restore relay status?)
test = 8; // jump to specific test
continue; // don't test for keypress
case 8: if (testSet != '\x01') {
test_78(); // turn off DCT test mode
}
test_80(); // get / display toggle switch status
break;
}
while (1) {
char ch = getKey();
if (ch == '\x13') test = repeatFrom; // REPEAT KEY PRESSED: repeat from given test
else if (ch == '\x1b') test++; // NEXT KEY PRESSED: do next test
else continue; // ANY OTHER KEY PRESSED: do nothing but query for a key press
break; // a key was pressed so we exit inner loop to do the test.
}
repeatFrom = 1; // assume repeat from first test unless changed
}
EDIT: had to move test_76() to its own state.
-
Today's IA are very good for translating one programming language into another...
here is a quick and dirty try at converting your code into C.
you will need the real device to test it, so I can't do it !
-
Today's IA are very good for translating one programming language into another...
To me, the assembly version is more readable.
-
It'll take a bit to digest that code.
I tried to transliterate the assembly instructions into C a while back and came up with some really clunky, ugly code.
When I instead started to group certain instructions together - i.e., from:
suite2
LDAA testSet
CMPA #$01
BEQ test15
JMP test20
to:
suite2:
if (testSet == 1) { test15(); }
else { test20(); }
things start to become easier to rewrite.
I just need some kind of 'do...while' or switch statement or something to handle those breakpoints where the operator can only press Repeat or Next to continue. :)
I eventually plan to use some kind of keyboard handler suited to whatever PIC or module I use, so instead of watching for matrix values, I would use flags like keyRepeat or keyNext respectively.
-
suite3_11
JSR getKey
CMPA #$13 ; repeat
BNE suite3_12
BRA suite3 ; re-run current test
suite3_12
CMPA #$1B ; next
BNE suite3_11
; we now continue to the next step
Gotos are very powerful in assembler, but in C it is the (small) functions that give you the power.
I would divide the tests into different functions, one for each test, and another function to ask the keyboard:
#define True (1)
#define False (0)
int tests(void) {
test_suite_1();
test_suite_2();
test_suite_3();
test_suite_4();
}
int test_suite_3(void) {
do {
// Current Suite 3 test
} while (kb_is_end() == False);
}
int kb_is_end() {
while (True) {
c = getchar();
if (c == 0x13) return False;
if (c == 0x1B) return True;
};
}
-
That's my plan. The original assembly as dumped from the EPROMs was absolutely horrendous - like it was written by an intern with an Assembly Language 101 book at hand.
I have since massaged the assembly into a more logical and readable version, with the test steps themselves moved into subroutines (followed by the existing subroutines).
Just need to get past this bit of coder's block.
Edit: To illustrate - this is the transliteration I eventually worked out:
testStep:
test_call();
checkpoint:
getKey(keyNext,keyRepeat);
if (keyRepeat == true) { goto testStep; }
else if (keyNext != true) { goto checkpoint; }
Was there a more elegant approach?
-
Primitive types (boolean) as parameters are pass-by-value so they won't be updated by the function.
You'd have to pass an address to them, like:
getKey(&keyNext,&keyRepeat);
Instead of using a boolean for each key, why don't use a #define to check for the key that was pressed, like:
#define KEY_REPEAT 0x13
#define KEY_NEXT 0x1b
char ch; // declare at top of block
testStep:
test_call();
while((ch = getKey()) != KEY_NEXT) {
if (ch == KEY_REPEAT) goto testStep;
}
-
That 'while' statement is what I was thinking of, but wasn't sure how to format it properly.
I'll see how well I do in rewriting one of the test suites and post back once I've gone through it. Thanks!
-
And it didn't take that long... here's my take on the DCT test group:
// Two-way unit tests: Distribution Control Terminal test suite
suite3:
test61(); // Read DCT Analog 1
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }
test62(); // Read DCT Analog 2
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }
test63(); // Read DCT Analog 3
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }
test64(); // Read DCT Analog 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }
if (optByte && 2 != 0) // this may be a flag for latched vs. timed relays
{
suite3_01:
test_70(); // download data from DCT
test_71(); // send message to DCT
test_72(); // strobe DCT relays
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3_01; }
test_73(); // write data back to DCT (restore relay status?)
}
else
{
test_75(); // get dctdata1 value from UUT
suite3_06:
test_76(); // DCT relay tests
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3_06; }
}
suite3_09:
if (testSet != 1) { test78(); } // turn off DCT test mode
test80(); // display toggle switch status
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite3; }
// We're done. Back to main menu
keyMask = %01001000;
goto loopMain;
// End of DCT tests
And the LMT-1xx group:
// LMT-1xx test suite (receive-only)
suite1:
if (rlyNum != 0)
{
test35a(); // exercise timed relays A - D
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite1; }
}
if (fctCtlNum != 0) { test40a(); } // exercise latched relay D
// We're done. Back to main menu
keyMask = %01001000;
goto loopMain;
// End of LMT-1xx tests
How does that look?
-
Looks good but I can do better by making the while getKey loop into a macro:
#define WAIT_ON_NEXT_OR_REPEAT(target) while((ch = getKey()) != KEY_NEXT) { if (ch == KEY_REPEAT) goto target; }
suite3:
test61(); // Read DCT Analog 1
WAIT_ON_NEXT_OR_REPEAT(suite3);
test62(); // Read DCT Analog 2
WAIT_ON_NEXT_OR_REPEAT(suite3);
test63(); // Read DCT Analog 3
WAIT_ON_NEXT_OR_REPEAT(suite3);
test64(); // Read DCT Analog 4
WAIT_ON_NEXT_OR_REPEAT(suite3);
if (optByte && 2 != 0) // this may be a flag for latched vs. timed relays
{
suite3_01:
test_70(); // download data from DCT
test_71(); // send message to DCT
test_72(); // strobe DCT relays
WAIT_ON_NEXT_OR_REPEAT(suite3_01);
test_73(); // write data back to DCT (restore relay status?)
}
else
{
test_75(); // get dctdata1 value from UUT
suite3_06:
test_76(); // DCT relay tests
WAIT_ON_NEXT_OR_REPEAT(suite3_06);
}
suite3_09:
if (testSet != 1) { test78(); } // turn off DCT test mode
test80(); // display toggle switch status
WAIT_ON_NEXT_OR_REPEAT(suite3);
// We're done. Back to main menu
keyMask = 0b01001000;
goto loopMain;
// End of DCT tests
Changed "keyMask = %01001000;" to "keyMask = 0b01001000;"
Or,
to minimize the generated code at every key check, you can call a function containing the key check loop instead.
int wasRepeatKeyPressed() {
char ch;
while((ch = getKey()) != KEY_NEXT) {
if (ch == KEY_REPEAT) return 1;
}
return 0;
}
#define WAIT_ON_NEXT_OR_REPEAT(target) if (wasRepeatKeyPressed()) goto target
-
So, how would I go about doing this?
int suiteId = 3; // start with suite3
for (;;) {
// Call suite
switch (suiteId) {
case 3: suite3(); break;
case 4: suite4(); break;
default: // unknown suite - do nothing
break;
}
// Check keyboard input
int nextSuiteId = -1; // set next suite undefined
while (nextSuiteId < 0) {
switch (getKey()) {
case 0x13: // repeat suite
nextSuiteId = suiteId;
break;
case 0x1b: // next suite
nextSuiteId = suiteId + 1;
break;
default: // unknown key - do nothing
break;
}
}
suiteId = nextSuiteId;
}
-
pqass: I'm really liking the idea of a macro, and I know there WILL be opportunities to add more as the program evolves.
But I see I need to do two things before I keep going:
One, I need to revisit the structure of the suite2 loops. I may need to tear the assembly down and rebuild from scratch, splitting it based on uutType = 2 and uutType = 4 (the third case, uutType = 1, is suite1). Like I said, the original assembly before I tided it up was horrendous.
The other is to find a C library I'd seen a while back for writing to a 4x20 LCD, as I will need to start laying out the display and building the corresponding macros for that as well.
-
See the code example above.
Regarding macros in C, it's generally advisable to avoid using them to prevent potential issues. Macros can make code harder to read and maintain, and they often introduce hidden errors that are difficult to detect and debug. Whenever possible, consider using const, inline functions, or enum for better type safety and code clarity.
For example:
#include <stdio.h>
#define true false
int main() {
if (true) {
printf("This should print, but it doesn't.\n");
} else {
printf("This should never print, but it does.\n");
}
return 0;
}
In this example, you typically don't see that true is redefined as false by a macro because this definition is hidden somewhere in a header file. At first glance, the code in the main() function looks correct but behaves differently from what you expect.
In addition, using macros limits the compiler's ability to perform type checking, which often leads to hidden errors that are difficult to detect.
The only genuinely useful feature of macros in C is conditional compilation using #ifdef. It allows you to include or exclude parts of the code based on specific conditions, which can be helpful for cross-platform compatibility, debugging, or configuring different build options. In all other cases, avoid using macros to reduce the number of potential problems in your code.
Historically, many header files were written at a time when the C language did not support constants and enums. As a result, macros were heavily used to define constants and other values. Unfortunately, this legacy remains, and in practice, you will often encounter macros in existing codebases. It is a historical artifact that developers must contend with, but whenever possible, it is better to use modern, type-safe alternatives such as const, enum, or inline functions.
-
No doubt, macros can get ugly. Keep it simple.
I'm using them to help improve readability in my reply#12 by removing the visual noise and minimizing the use of labels.
The state machine in reply#3 is more compact but is harder to read compared to your linear flow in reply#12.
...find a C library...for writing to a 4x20 LCD
See my minimalist one here (https://www.eevblog.com/forum/microcontrollers/initialising-a-4x20-lcd-with-i2c-interface/msg4265080/#msg4265080). Just adjust the lcdSend() function to send to a SPI (74HC595) attached or 4-bit parallel attached LCD.
For a LCD refresher video and HD44780 datasheet see here (https://www.eevblog.com/forum/beginners/generic-16x2-lcd-unit/msg3882629/#msg3882629).
-
I'm using them to help improve readability in my reply#12 by removing the visual noise and minimizing the use of labels.
Avoid using macros and goto statements in C code, as their presence is considered as a sign of extremely poor code quality (also called "shitty code" or "spaghetti code").
You don't need macros or goto statements to make your code more readable or easier to debug. In fact, they tend to do the opposite - making the code harder to understand and introducing potential bugs that can be difficult to track down. Instead, focus on writing clean, structured code with clear control flow and type-safe constructs.
If you feel the need to use a macro or goto statement in your code, it's a strong indication that something is fundamentally wrong with your approach.
For example, the projects I have worked on contained gigabytes (if not terabytes) of source code in various languages, and none of them included even a single goto statement.
-
As always, ignore radiolisterer. Macros are very much present in every non-trivial real world high-quality project for very good reasons; they are one of the fundamental reasons why C still is a popular language. Used right, they make the difference between unmaintainable copy-pasta spaghetti mess, and a readable/maintainable project.
The name of the relevant concept is Don't Repeat Yourself.
And then again, any feature can be abused.
But I'm sure radiolistener is happy copy-pasting code or using ChatGPT to generate it. Such write-only code indeed does not need to use macros.
Goto is an excellent tool for people management. Once you hear stuff like... "goto is considered bad practice which leads to spaghetti code"... you instantly know that this person is operating like a bot with very little neuron activation in brain. They are beyond salvage and considered harmful, and thusly ignored; then, the project can go on, using goto for the usual purposes like exiting an outer loop (when language lacks labelled loop bodies), or error management (when language lacks try-catch exceptions).
-
As always, ignore radiolisterer.
Let's keep the discussion respectful and focused on technical arguments rather than insulting personalities. It's perfectly fine to disagree, but dismissing someone's input by telling others to ignore them adds no value to the conversation.
It's more productive to debate the merits of different approaches based on facts and best practices rather than suggesting whose opinions should or shouldn't be heard. Let’s keep the conversation constructive.
So please refrain from resorting to cheap trolling and personal attacks by shifting the discussion towards personalities rather than the technical subject at hand
Macros are very much present in every non-trivial real world high-quality project for very good reasons; they are one of the fundamental reasons why C still is a popular language. Used right, they make the difference between unmaintainable copy-pasta spaghetti mess, and a readable/maintainable project.
The name of the relevant concept is Don't Repeat Yourself.
While it's true that macros are still commonly found in modern projects, they are largely a relic from older versions of C compilers, where the language syntax was less developed, and features like enum, constants, and inline functions weren't available. As a result, macros were used to achieve similar functionality.
Refactoring old legacy code is often a complex and time-consuming task that typically doesn't provide significant benefits, which is why such code is often left as is. However, it is important to acknowledge that macros come with well-documented downsides, including reduced readability, lack of type checking, and an increased potential for hidden bugs.
Many high-quality, modern projects actively avoid macros in favor of safer and more maintainable alternatives, such as const, inline functions, and enum. These alternatives not only improve the readability and safety of the code but also support better maintainability in the long term.
In other words, the old code using macros has already been debugged and is functioning as expected. While refactoring it to modern syntax will result in more readable and safer code, and you may uncover and fix some issues in the process, it will require a significant investment of time in development and debugging to achieve a version of the code that ultimately behaves in much the same way as the original. As a result, such legacy code is often left as-is. Additionally, macros may sometimes be used in new code to maintain consistency within the project, but this does not imply that it is the best or most appropriate approach for writing readable and safe code.
Goto is an excellent tool for people management. Once you hear stuff like... "goto is considered bad practice which leads to spaghetti code"... you instantly know that this person is operating like a bot
It’s important to separate technical practices from personal opinions. When someone says, "goto is considered bad practice and leads to spaghetti code," it typically means they understand the issues that come with using goto - such as creating hard-to-follow control flow and making debugging more difficult. Recognizing these problems is a sign of someone being aware of best practices and trying to avoid common pitfalls.
I worked in the highly regulated medical device industry, where the quality of code is critically important. This is because the code we wrote directly impacted human lives - it was responsible for the success of heart surgeries and other critical procedures. In such an environment, every line of code had to be meticulously reviewed and tested to ensure reliability and safety, as any failure could have severe consequences.
If you’ve had heart surgery at one of the leading hospitals in the United States, Israel, or Europe, it’s quite likely that my code was involved in the procedure. The software I developed played a critical role in ensuring the success of such complex and life-saving operations.
Engineers working on such projects understand the risks that come with poorly structured code. In fact, goto is often avoided precisely because it can introduce maintainability and reliability issues. In our company, the use of goto in code reviews or interviews would have been a major red flag, and anyone who demonstrated a reliance on it would not have passed the interview.
I understand that not all projects require such strict coding practices, and in my personal hobby projects, I sometimes take a more relaxed approach, but I never use goto statement even in my hobby projects and don't see any reason to use it. So, while goto might be considered acceptable in some niche cases, in general, it’s better to follow practices that enhance readability, maintainability, and safety - which is why goto is discouraged in modern development.
-
Gotos can be useful in C, but only for particular purposes described.
Assembly uses a lot of gotos, that you should not use in C.
-
Interestingly, while reviewing the code of a hobby project (disassembler) I wrote 30 years ago, I discovered a goto statement in one of the algorithms. :)
What’s even more interesting is that I vividly remember the moment when I wrote this code - at the time, I simply couldn't find a better solution, even though I was already aware of the drawbacks of using goto. Now, with more experience, I was able to easily refactor the code to make it more readable, without relying on goto. This highlights that the desire to use goto is not due to its utility, but rather a lack of experience and knowledge, when a developer hasn’t yet encountered better approaches to writing code and hasn’t found a more effective solution.
Now, I don't see any reason to use goto at all. And it's important to note - not because it's considered bad practice, not for religious reasons, and not because any particular group of people or company believes it's wrong, but simply because I don't see any practical situations where goto would be beneficial, especially since I know more effective solutions that can be implemented without it.
-
Here's the rewrite after some structural work to get the three two-way suites into one.
I can't see how to minimize the goto statements - most are attached to conditionals, the only 'hard' goto statements are returning to the main loop or to the error handler.
-
Now, I don't see any reason to use goto at all. And it's important to note - not because it's considered bad practice, not for religious reasons, and not because any particular group of people or company believes it's wrong, but simply because I don't see any practical situations where goto would be beneficial, especially since I know more effective solutions that can be implemented without it.
That's an ultra-common topic as it seems and comes back on a regular basis.
You'll find the usual, "goto's are bad" and "those who say goto's are bad are just ignorant wankers with no practical experience".
I'm not sure either are very useful, but hey. There's little as polarizing as programming topics. And politics.
I often like to start with the obvious, that is the rationale of the original paper it originates from, which was just trying to convince people of the benefits of structured programming, which was absolutely not a given at the time. These days, nobody reaosnable would even question "structured programming", so that context is almost entirely lost.
The second point is that, apart from assembly with "branches", most uses of "goto" are in C and C++ when it's a convenient and efficient way of breaking out of some nested loops, or for error handling, where you have a function with many possible paths of error and a single point to go to to handle the error before returning. That's mostly for lack of better constructs, not at all because goto is cute, even less so an elegant way of dealing with program flow. But it works given the limitations of those languages.
Some other languages have proper ways of dealing with the same, like named loops (which are coming with C23 if I'm not mistaken?) and 'defer' constructs. I don't think anyone sane would prefer using "goto" rather than those two alternatives, but of course, YMMV.
Now even in C, there are ways you can often avoid goto for typical error handling, which I tend to prefer these days, although that's relatively recent. Instead of using goto, I'll wrap code that can produce errors in "do {...} while (false)" constructs, which I just 'break' out of after setting an error value, in case of error. The error value is tested after this "loop", and that often looks cleaner. Additional benefit is you can ultra easily turn this construct into "retry" construct by changing changing the do...while to a for with a certain number of iterations.
For breaking out of nested loops, unfortunately, I have no magic trick (until we get named loops). One common way of avoiding 'goto' in this case is to use flags, but that often looks clunky and is possibly less efficient, depending on the order in which you place the flag test in the loop conditions. Occasionally, it can make things more readable, as it shows the complete condition of a loop in only one place, but most often, it's just clunky.
-
Here's the rewrite after some structural work to get the three two-way suites into one.
I can't see how to minimize the goto statements - most are attached to conditionals, the only 'hard' goto statements are returning to the main loop or to the error handler.
Just remove all labels from your code. Use functions instead. That's pretty easy, just write:
void suite2(int testSet) {
if (testSet == 1) {
test15(); // download address to UUT
}
...
}
instead of
suite2:
...
The issue with your code is that you create spaghetti code by using multiple labels and jumping back and forth between different parts of the program. These jumps are unnecessary - you simply need to structure the execution flow sequentially without this mix of jumps. I recommend removing all goto statements and labels and rewriting the code in a more structured and readable manner.
Here is example on how to do it: https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5863129/#msg5863129 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5863129/#msg5863129)
Simply forget about the goto statement entirely and write code as if the compiler doesn’t support it at all. Before long, you’ll notice how much easier it becomes to write and read your code. ;)
If you're struggling to implement a feature and feel the urge to use goto, just stop and forget about it. Instead, take a step back and think about how to achieve the same result without goto - it’s actually much easier than it seems. If you’re stuck, it likely means you’ve fixated on goto as the solution and need a way out of that mindset. Feel free to share what you're trying to accomplish here, and we’ll help you find a better approach.
Just remember, C code should not contain even a single goto.
-
I have some assembly code I want to eventually rewrite into C, and I have isolated the four main loops (there's still an interrupt, but that comes later).
...
So, how would I go about doing this?
Determine what the application (or part of application) is specified to do. Use any technique necessary to end up with a black box specification.
Then ignore the current implementation, and completely reimplement that specification in the language of your choice.
If you are required to reimplement X exactly including bugs, find another job.
-
Is the code hand-written or the output of a compiler? There are some pretty decent decompilers around that can often recreate the original C, you can use the dogbolt decompiler explorer (https://dogbolt.org/) to see which one works best.
-
Is the code hand-written or the output of a compiler? There are some pretty decent decompilers around that can often recreate the original C, you can use the dogbolt decompiler explorer (https://dogbolt.org/) to see which one works best.
With -O3 etc optimisation? "Reversing" some of these optimisations is relatively straightforward, but others aren't: https://medium.com/@guannan.shen.ai/compiler-optimizations-46db19221947 I'm sure there are others :)
Don't forget that the variable qualifiers and compiler flags aren't available and won't be reinserted by the decompiler. Without those, any modification and recompilation of the decompiled code might cause it to subtly fail.
-
Gotos can be useful in C, but only for particular purposes described.
I'm not aware of any specific scenarios where goto would be genuinely useful. Could you provide some examples?
Update: After some thought, I came up with a scenario where goto could be useful—if your goal is to obfuscate code, making it difficult to read and analyze, then goto can certainly help with that. This might be useful when writing viruses or other malicious software, but it has no place in conventional software development.
goto can be particularly effective when you need to make code extremely convoluted, transforming what would otherwise be a clean and structured execution flow into something resembling an explosion at a spaghetti factory. By scattering jumps across different parts of the program, it becomes significantly harder to understand, maintain, and debug—qualities that are the exact opposite of what good software engineering aims for.
-
Good grief, Charlie Brown!
You'd think that I'd ripped a loud and vile-smelling one in the middle of a wedding or something.
Mind you, this code I presented as the starting point was AFTER I'd already gone through and rearranged it for a clearer flow, and the second round came after further insight.
I ALREADY try and replace as many goto statements as I can. As I gain a better understanding of this code, I'll have future opportunities to rewrite the code for better flow.
And, the act of rewriting the code has helped me to understand what it's doing, giving me further opportunities to streamline it even more.
I mean, COME ON. You can't expect everyone to have a [censored] PhD in CompSci to write C
-
Your code is extremely difficult to read and understand due to the excessive use of goto statements and labels. This creates chaotic control flow, making the execution fragmented, hard to follow, and prone to errors. Maintaining and modifying such code is unnecessarily complicated.
There is absolutely no need to use goto here. Instead, you should structure your logic using functions, loops, and conditional statements. Break the code into smaller, meaningful functions, and use structured programming principles to guide the execution flow naturally.
And let’s be clear - this isn't some advanced topic that requires a professor to solve. Any schoolboy with a little experience can rewrite this in a structured way without goto. It’s just a matter of approaching the problem correctly.
If you're struggling to refactor a specific part, describe what you're trying to achieve, and I'll help you restructure it properly.
The best way in this case in my opinion is just to discard this code entirely and start fresh with a properly structured approach. Trying to untangle and refactor this goto-ridden code will likely take more effort than writing a new, well-organized version from scratch.
If you don't have extensive experience, deciphering what this code actually does will be extremely challenging. Understanding such an unstructured flow requires deep knowledge of both low-level programming concepts and high-level software architecture, as well as significant experience in reading and restructuring complex code.
Instead of struggling with this, it's far more efficient to rethink the logic and implement it properly using functions, loops, and clean control flow from scratch. You'll end up with code that's easier to maintain, debug, and extend in the future.
In short, writing code without goto doesn’t require a PhD in Computer Science or even extensive experience. However, thoroughly understanding and untangling a codebase filled with goto statements—like the one you've presented—is a genuinely complex task. It demands significant expertise, deep knowledge of programming at both low and high levels of abstraction, and extensive experience. In this case, the skills and knowledge of a PhD in Computer Science would actually be highly beneficial.
Looking at this code, it's quite evident that the person who wrote it didn’t fully understand what the code actually does. The excessive use of goto and arbitrary jumps suggests a lack of structured design and a poor grasp of fundamental programming principles.
Because of this, refactoring this code properly is a difficult task - not just because you need to rewrite it correctly, but because you first have to decipher and reverse-engineer a messy and flawed implementation to even understand what it was supposed to do in the first place.
-
Gotos can be useful in C, but only for particular purposes described.
I'm not aware of any specific scenarios where goto would be genuinely useful. Could you provide some examples?
Update: After some thought, I came up with a scenario where goto could be useful—if your goal is to obfuscate code, making it difficult to read and analyze, then goto can certainly help with that. This might be useful when writing viruses or other malicious software, but it has no place in conventional software development.
goto can be particularly effective when you need to make code extremely convoluted, transforming what would otherwise be a clean and structured execution flow into something resembling an explosion at a spaghetti factory. By scattering jumps across different parts of the program, it becomes significantly harder to understand, maintain, and debug—qualities that are the exact opposite of what good software engineering aims for.
https://github.com/torvalds/linux/blob/master/fs/ext4/migrate.c
Linux kernel sources are plenty of examples.
-
https://github.com/torvalds/linux/blob/master/fs/ext4/migrate.c
Linux kernel are plenty of examples.
The example you provided is not a case where goto should be used, rather, it's an instance of improper usage of goto, likely stemming from the author's lack of experience with structured programming in C.
The use of goto in this case mirrors low-level assembly-style thinking, which is often a result of an individual coming from an assembly language background. While assembly languages often use jump instructions like goto, C provides more expressive and structured control flow mechanisms that make the code more readable and maintainable.
Lets see how it use goto:
if (retval < 0)
goto err_out;
path = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
if (IS_ERR(path))
retval = PTR_ERR(path);
err_out:
this code fragment can be easily replaced with this one, which don't needs to use goto at all:
if (retval >= 0) {
path = ext4_ext_insert_extent(handle, inode, path, &newext, 0);
if (IS_ERR(path))
retval = PTR_ERR(path);
}
This approach achieves the same result but avoids unnecessary jumps, improving the clarity of the logic.
In summary, this example demonstrates an unnecessary use of goto rather than a legitimate need for it. It's a common mistake made by programmers transitioning from low-level languages, where jumps are more common, to higher-level languages like C. With more experience in C, one would recognize that such a structure can be replaced with better alternatives.
-
Gotos can be useful in C, but only for particular purposes described.
I'm not aware of any specific scenarios where goto would be genuinely useful. Could you provide some examples?
Reading the book "Modern C" by Jens Gustedt will be, no doubt, beneficial in this case.
-
Reading the book "Modern C" by Jens Gustedt will be, no doubt, beneficial in this case.
I didn't ask for recommendations on what to read in order to write poor-quality code, as I strive to avoid that. I asked for specific examples where the use of goto is truly necessary and beneficial. Could you provide such examples?
From my experience, when you feel the urge to use goto, it usually indicates that something in your design or code structure is wrong. It suggests that perhaps the wrong design approach or structure has been chosen. In such cases, rather than resorting to goto, it's better to take a step back, analyze the code, and choose more suitable structures that eliminate the need for goto altogether.
If your goal is to learn how to write intentionally convoluted and low-quality code, I would suggest to learn the Brainfuck programming language written by Urban Müller. Here's an example of code written in this language:
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
You can do similar things in C, for example, here is working C code which demonstrate macros using:
https://github.com/ioccc-src/winner/blob/master/2020/endoh3/prog.c
#define/**/Q(x,y)char*/* */q=y#x","#y")",*p,s[x;}
/*IOCCC'20*/#include/* */<stdio.h>/*-Qlock-*/
int(y),x,i,k,r;Q(9/* 12 */<<9];float(o)[03];
void(P)(){*o=r<0/* 11 1 */?r:-r;o[1]=39.5;
o[2]=22.5;for(k/* 10 2 */=0;++k<39;*o*=i
/6875.5/(k%2?k/* */:-k))y=o[1+k%2
]+=*o;k=o[2];/* 9 o-------> 3 */p=s+y+k/2*80;
}int(main)()/* / */{for(p=s;+i<
1839;*q>32?k/* 8 L 4 */=i++/80-11,y
=(750>r*r+k/* 7 5 */*k*4)*4+y/2
,*p++=r<41?/* 6 */y?"0X+0X+!"
[y-1]-1:+*q/* */++:10:*q++)
r=i%80-38;;/* */;for(x=13,r
=20;i=3600*/* \ / -------+ */--x,i;*p++=
"OISEA2dC8e"/* \ / ------ | */[x%10],*p+=x
/10*41)P();r/* \ / ------ | */=10;;sscanf(
__TIME__,"%d"/* \ / ------ | */":%d:%d",&k,&
x,&i);for(i+=(/* X ------ | */k*60+x)*60;18+
r;*p=k%2?*p%2?+/* __/ \__ | | */59:44:*p>39?59:
39,i=!r--?i%3600/* / \ / \ | | */*12:i)P();puts(s
),"#define/**/Q(x"/* \__/ \__/ +--+ */",y)char*q=y#x\","
"\"#y\")\",*p,s[x;}"/* */"/*IOCCC'20*/#inclu"
"de<stdio.h>/*-Qlock-"/* */"*/int(y),x,i,k,r;Q(")
Another example with macros:
https://github.com/ioccc-src/winner/blob/master/2020/carlini/prog.c
#include <stdio.h>
#define N(a) "%"#a"$hhn"
#define O(a,b) "%10$"#a"d"N(b)
#define U "%10$.*37$d"
#define G(a) "%"#a"$s"
#define H(a,b) G(a)G(b)
#define T(a) a a
#define s(a) T(a)T(a)
#define A(a) s(a)T(a)a
#define n(a) A(a)a
#define D(a) n(a)A(a)
#define C(a) D(a)a
#define R C(C(N(12)G(12)))
#define o(a,b,c) C(H(a,a))D(G(a))C(H(b,b)G(b))n(G(b))O(32,c)R
#define SS O(78,55)R "\n\033[2J\n%26$s";
#define E(a,b,c,d) H(a,b)G(c)O(253,11)R G(11)O(255,11)R H(11,d)N(d)O(253,35)R
#define S(a,b) O(254,11)H(a,b)N(68)R G(68)O(255,68)N(12)H(12,68)G(67)N(67)
char* fmt = O(10,39)N(40)N(41)N(42)N(43)N(66)N(69)N(24)O(22,65)O(5,70)O(8,44)N(
45)N(46)N (47)N(48)N( 49)N( 50)N( 51)N(52)N(53 )O( 28,
54)O(5, 55) O(2, 56)O(3,57)O( 4,58 )O(13, 73)O(4,
71 )N( 72)O (20,59 )N(60)N(61)N( 62)N (63)N (64)R R
E(1,2, 3,13 )E(4, 5,6,13)E(7,8,9 ,13)E(1,4 ,7,13)E
(2,5,8, 13)E( 3,6,9,13)E(1,5, 9,13)E(3 ,5,7,13
)E(14,15, 16,23) E(17,18,19,23)E( 20, 21, 22,23)E
(14,17,20,23)E(15, 18,21,23)E(16,19, 22 ,23)E( 14, 18,
22,23)E(16,18,20, 23)R U O(255 ,38)R G ( 38)O( 255,36)
R H(13,23)O(255, 11)R H(11,36) O(254 ,36) R G( 36 ) O(
255,36)R S(1,14 )S(2,15)S(3, 16)S(4, 17 )S (5, 18)S(6,
19)S(7,20)S(8, 21)S(9 ,22)H(13,23 )H(36, 67 )N(11)R
G(11)""O(255, 25 )R s(C(G(11) ))n (G( 11) )G(
11)N(54)R C( "aa") s(A( G(25)))T (G(25))N (69)R o
(14,1,26)o( 15, 2, 27)o (16,3,28 )o( 17,4, 29)o(18
,5,30)o(19 ,6,31)o( 20,7,32)o (21,8,33)o (22 ,9,
34)n(C(U) )N( 68)R H( 36,13)G(23) N(11)R C(D( G(11)))
D(G(11))G(68)N(68)R G(68)O(49,35)R H(13,23)G(67)N(11)R C(H(11,11)G(
11))A(G(11))C(H(36,36)G(36))s(G(36))O(32,58)R C(D(G(36)))A(G(36))SS
#define arg d+6,d+8,d+10,d+12,d+14,d+16,d+18,d+20,d+22,0,d+46,d+52,d+48,d+24,d\
+26,d+28,d+30,d+32,d+34,d+36,d+38,d+40,d+50,(scanf(d+126,d+4),d+(6\
-2)+18*(1-d[2]%2)+d[4]*2),d,d+66,d+68,d+70, d+78,d+80,d+82,d+90,d+\
92,d+94,d+97,d+54,d[2],d+2,d+71,d+77,d+83,d+89,d+95,d+72,d+73,d+74\
,d+75,d+76,d+84,d+85,d+86,d+87,d+88,d+100,d+101,d+96,d+102,d+99,d+\
67,d+69,d+79,d+81,d+91,d+93,d+98,d+103,d+58,d+60,d+98,d+126,d+127,\
d+128,d+129
char d[538] = {1,0,10,0,10};
int main() {
while(*d) printf(fmt, arg);
}
There are many other ways to write code that is nearly unreadable and difficult to understand, but this is certainly not something you should focus on when aiming for good software engineering practices.
-
https://www.eevblog.com/forum/general-computing/is-it-a-good-idea-to-use-goto-statement/ (https://www.eevblog.com/forum/general-computing/is-it-a-good-idea-to-use-goto-statement/)
void foo()
{
if (!doA())
goto exit;
if (!doB())
goto cleanupA;
if (!doC())
goto cleanupB;
/* everything has succeeded */
return;
cleanupB:
undoB();
cleanupA:
undoA();
exit:
return;
}
-
Reading the book "Modern C" by Jens Gustedt will be, no doubt, beneficial in this case.
I didn't ask for recommendations on what to read in order to write poor-quality code, as I strive to avoid that. I asked for specific examples where the use of goto is truly necessary and beneficial. Could you provide such examples?
That book contains exactly what you asked for. But you will not read anything that, even remotely, goes against your "best practices". The rest of your message is unintended, irrelevant and childish. There's none so blind as he who will not see.
-
Is the code hand-written or the output of a compiler? There are some pretty decent decompilers around that can often recreate the original C, you can use the dogbolt decompiler explorer (https://dogbolt.org/) to see which one works best.
With -O3 etc optimisation? "Reversing" some of these optimisations is relatively straightforward, but others aren't
It depends on how the code's built, I know some embedded code is built with -O0 to avoid unpleasant surprises inserted by the compiler, which produces roughly the same output as the CompCert verified compiler. Also some of the reversers will recognise some compiler idioms and reproduce the original code even in the presence of optimisation... that's why I suggested dogbolt, it lets you explore which, if any, produce the best output.
-
I'm not aware of any specific scenarios where goto would be genuinely useful. Could you provide some examples?
[Anti-goto tirade]
Just for reference the paper was called Go To Statement Considered Harmful and was specifically targeted at its overuse in FORTRAN which had little in the way of modern control statements. We've moved on a bit in the half-century since then.
It was also not called Goto Considered the Spawn of Beelzebub and Anyone Who Uses It is a Sinner who Should Burn in the Fires of Hell.
-
Is the code hand-written or the output of a compiler? There are some pretty decent decompilers around that can often recreate the original C, you can use the dogbolt decompiler explorer (https://dogbolt.org/) to see which one works best.
With -O3 etc optimisation? "Reversing" some of these optimisations is relatively straightforward, but others aren't
It depends on how the code's built, I know some embedded code is built with -O0 to avoid unpleasant surprises inserted by the compiler, which produces roughly the same output as the CompCert verified compiler. Also some of the reversers will recognise some compiler idioms and reproduce the original code even in the presence of optimisation... that's why I suggested dogbolt, it lets you explore which, if any, produce the best output.
It does indeed "depend"; no general statement can be made.
Even with mildly optimised code I've seen some very confusing (but correct) code reordering. That was most clearly seen when single stepping and/or using the IDE's tools which revealed the control flow paths flow to determine the best/worst case "mainloop" execution time.
As for "surprises" from the compiler, strictly speaking the compiler would have been correct. But C/C++ is so complex and ill-defined that even the language design committee refused to believe what they had created. The tool becomes part of the problem, not part of the solution. But that's a different story :)
-
void foo()
{
if (!doA())
goto exit;
if (!doB())
goto cleanupA;
if (!doC())
goto cleanupB;
/* everything has succeeded */
return;
cleanupB:
undoB();
cleanupA:
undoA();
exit:
return;
}
what is the reason for goto in your example?
Here equivalent code but with no goto:
void foo() {
if (!doA()) {
return;
}
if (!doB()) {
undoA();
return;
}
if (!doC()) {
undoB();
undoA();
return;
}
/* everything has succeeded */
return;
}
As you can see, its much easier to read and support. And there is no need to use goto at all.
-
That book contains exactly what you asked for. But you will not read anything that, even remotely, goes against your "best practices". The rest of your message is unintended, irrelevant and childish. There's none so blind as he who will not see.
What you think about me is entirely irrelevant in this discussion - I didn’t ask for your opinion about me. I asked a specific technical question.
If you want to engage in a discussion, provide a concrete technical answer. Your personal thoughts about me are of no interest and have no place in this conversation.
In a professional discussion, evading a direct answer through manipulation is unacceptable. Instead of providing a concrete example when asked, you suggest reading an entire book. This is equivalent to being asked what your own statement means and responding by recommending an encyclopedia.
Such behavior is nothing more than an attempt to avoid answering, which is unacceptable in a mature and professional discussion. This is what constitutes childish behavior.
Additionally, attempting to shift the discussion from a technical topic to a discussion about individuals is equally unacceptable manipulation in a mature, professional debate. This is just another way to evade the question - by resorting to personal attacks in the hope that the opponent will become distracted and the original question will be forgotten, eliminating the need to answer it.
Please refrain from using such childish manipulation tactics on an engineering forum by avoiding direct answers and posting unintended and irrelevant responses. You were asked a specific question - if you can answer it, do so. If you don’t have an answer, simply say so.
-
In a professional discussion, evading a direct answer through manipulation is unacceptable.
Not always. As Wolfgang Pauli famously put it, "What you said was so confused that one could not tell whether it was nonsense or not" and "That is not only not right; it is not even wrong".
In such cases it is difficult and/or pointless to attempt to refute the specific point.
Instead of providing a concrete example when asked, you suggest reading an entire book.
Sometimes both parties can gain by referring to a well-thought through text on the subject, rather than wasting time on a poorly worded response to a particular point. One gains time, the other (possibly) gains understanding.
-
In a professional discussion, evading a direct answer through manipulation is unacceptable.
Not always. As Wolfgang Pauli famously put it, "What you said was so confused that one could not tell whether it was nonsense or not" and "That is not only not right; it is not even wrong".
In such cases it is difficult and/or pointless to attempt to refute the specific point.
Your repeated attempts to evade direct answers and manipulate the discussion by labeling opposing views as "wrong" simply because you personally find them unclear indicate that you are not genuinely interested in a technical discussion. Instead, you are engaging in trolling -constantly avoiding direct responses and resorting to manipulative tactics in every reply.
This kind of behavior is unacceptable on an engineering forum. Please refrain from such manipulations and engage in a proper, technical discussion.
Instead of providing a concrete example when asked, you suggest reading an entire book.
Sometimes both parties can gain by referring to a well-thought through text on the subject, rather than wasting time on a poorly worded response to a particular point. One gains time, the other (possibly) gains understanding.
Do you seriously believe that directing someone to read general-purpose books, instead of providing a direct answer to a specific technical question, is an effective way to save their time?
If you are unable to formulate an answer yourself and instead suggest reading someone else’s book, this suggests that you have read the book but failed to fully grasp its content.
This makes it even more perplexing that you chose to engage in a debate without being able to substantiate your own opinion - while simultaneously recommending books that you yourself did not fully understand.
After all, it is quite evident that you are unable to substantiate your claim that the goto statement in C is beneficial. By continuously evading a direct answer, you have demonstrated that your opinion lacks any solid foundation or supporting arguments. Regardless of whether there are specific edge cases where goto might be justified, you have been unable to provide even a single concrete example to support your stance.
I, on the other hand, have already mentioned cases where goto could be justified - such as in code obfuscation, where the goal is to deliberately make the code difficult to read and analyze. It may be useful for different kind of malware, viruses, etc, where developer needs to hide code algorithms and make it more confusing for more difficult analysis. However, I have yet to see a situation in conventional programming where goto is truly necessary and cannot be replaced with a more structured approach.
-
In a professional discussion, evading a direct answer through manipulation is unacceptable.
Not always. As Wolfgang Pauli famously put it, "What you said was so confused that one could not tell whether it was nonsense or not" and "That is not only not right; it is not even wrong".
In such cases it is difficult and/or pointless to attempt to refute the specific point.
Your repeated attempts to evade direct answers and manipulate the discussion by labeling opposing views as "wrong" simply because you personally find them unclear indicate that you are not genuinely interested in a technical discussion. Instead, you are engaging in trolling -constantly avoiding direct responses and resorting to manipulative tactics in every reply.
This kind of behavior is unacceptable on an engineering forum. Please refrain from such manipulations and engage in a proper, technical discussion.
Instead of providing a concrete example when asked, you suggest reading an entire book.
Sometimes both parties can gain by referring to a well-thought through text on the subject, rather than wasting time on a poorly worded response to a particular point. One gains time, the other (possibly) gains understanding.
Do you seriously believe that directing someone to read general-purpose books, instead of providing a direct answer to a specific technical question, is an effective way to save their time?
If you are unable to formulate an answer yourself and instead suggest reading someone else’s book, this suggests that you have read the book but failed to fully grasp its content.
This makes it even more perplexing that you chose to engage in a debate without being able to substantiate your own opinion - while simultaneously recommending books that you yourself did not fully understand.
After all, it is quite evident that you are unable to substantiate your claim that the goto statement in C is beneficial. By continuously evading a direct answer, you have demonstrated that your opinion lacks any solid foundation or supporting arguments. Regardless of whether there are specific edge cases where goto might be justified, you have been unable to provide even a single concrete example to support your stance.
I, on the other hand, have already mentioned cases where goto could be justified - such as in code obfuscation, where the goal is to deliberately make the code difficult to read and analyze. However, I have yet to see a situation in conventional programming where goto is truly necessary and cannot be replaced with a more structured approach.
What are you on about?!
(And it would do you good to look in the mirror)
-
What are you on about?!
(And it would do you good to look in the mirror)
I am discussing the topic - the use of goto in C when translating code from assembly to C. Meanwhile, you continue attempting to shift the conversation toward personal matters, which is entirely inappropriate in a technical discussion.
Your suggestion to "look in the mirror" is irrelevant and out of place. I did not ask for personal advice, I asked a specific technical question - provide an example where goto is truly necessary and cannot be replaced with conventional structured code that avoids goto.
If you can provide an answer to the question asked, simply do so, and we can discuss it. If you cannot, then please refrain from childish posting irrelevant distractions, manipulative remarks, or attempts to shift the discussion toward personal matters. Let's keep the conversation technical and on-topic, okay?
-
https://www.wscubetech.com/resources/c-programming/goto (https://www.wscubetech.com/resources/c-programming/goto)
-
https://www.wscubetech.com/resources/c-programming/goto (https://www.wscubetech.com/resources/c-programming/goto)
I didn't asked what is goto and how it works, I assume anyone here knows that.
I asked the example where you cannot replace it with conventional code which don't use goto.
-
In the same article, after the introduction, he explains some uses of goto, its advantages and disadvantages.
One application is to exit two nested loops at once.
Another application is the one I posted earlier, managing input/output files with errors and without having to repeat closing code of open files.
Advantages of goto in C
1. Simplifies Error Handling
The goto statement is useful for handling errors and cleanup in a program, especially when dealing with multiple resources like file operations, memory allocation, or sockets. It helps consolidate cleanup code in one place, improving maintainability.
2. Exiting Deeply Nested Loops
In complex programs with multiple nested loops, goto can simplify the process of breaking out of all loops when a specific condition is met, without additional flags or logic.
3. Reduces Code Duplication
The goto statement can eliminate repetitive code by jumping to a specific labeled section for common operations, such as cleanup tasks.
4. Improves Readability in Certain Scenarios
While generally avoided for readability, in some cases like simple error handling or single jumps, goto can make the program flow easier to understand.
5. Useful in Low-Level Programming
In systems programming, goto is often employed in assembly-level logic or hardware-related programming where precise control over the flow of execution is required.
6. Handling Unpredictable Conditions
When program logic involves dealing with unexpected or edge-case scenarios, goto provides a direct way to handle such situations without overly complex logic.
-
On the other hand...
Disadvantages of goto in C
1. Reduces Code Readability
Using goto can make the program flow non-linear, making it harder for others (and even yourself) to understand the logic at a glance.
2. Leads to "Spaghetti Code"
Excessive use of goto results in tangled, disorganized code that jumps arbitrarily, making debugging and maintenance a nightmare.
3. Difficult to Debug
Jumping across the program disrupts the natural execution flow, making it challenging to trace the sequence of execution during debugging.
4. Error-Prone
Improper use of goto can lead to logical errors, such as skipping important code sections or infinite loops, especially in large programs.
5. Breaks Structured Programming Principles
Modern programming emphasizes structured and modular code, where constructs like loops, functions, and conditionals are preferred. goto undermines these principles.
6. Alternatives Are Better
In most cases, structured constructs like break, continue, return, and exception handling can achieve the same result as goto in a cleaner way.
7. Not Recommended in Modern Programming
With the availability of advanced constructs and better error-handling mechanisms in modern languages, goto is considered outdated and unnecessary for most applications.
8. Leads to Poor Maintainability
As programs evolve, maintaining goto-heavy code becomes increasingly difficult, especially when trying to refactor or extend functionality.
-
I asked the example where you cannot replace it with conventional code which don't use goto.
This does not exist. In structured programming you can ALWAYS replace goto with other operations.
We can only talk about where goto may be more effective/fast/clean than other solutions. And as you rightly pointed out, goto can probably be more effective but at the same time more insecure and error prone.
-
On the other hand...
Disadvantages of goto in C
I didn't ask for copy-pasted quotes from some online article.
I asked a simple and specific question - can you provide an example where goto is truly necessary and cannot be replaced with conventional structured code that avoids goto? Do you have one?
Articles are written by people like everyone else, and people make mistakes. That's why you should think for yourself instead of blindly relying on something just because someone wrote it on the internet.
This does not exist. In structured programming you can ALWAYS replace goto with other operations.
Well. I'm glad you finally admitted it. :)
We can only talk about where goto may be more effective than other solutions. And as you rightly pointed out, goto can probably be more effective but at the same time more insecure and error prone.
Are you serious? What makes you think that avoiding goto leads to more insecure and error-prone code? :o
Doesn't the example provided by the topic author clearly demonstrate that using goto results in code that even the original author struggles to understand? Do you really consider that to be more secure and less error-prone than straightforward, readable code, where the author fully understands what they are doing and which can be easily reviewed and analyzed for errors?
-
You misunderstood me. I am agreeing with you by saying that goto is error prone.
I am just saying that goto is used in C and there are not always the reasons you gave for avoiding it at all costs.
-
Here equivalent code but with no goto:
void foo() {
if (!doA()) {
return;
}
if (!doB()) {
undoA();
return;
}
if (!doC()) {
undoB();
undoA();
return;
}
/* everything has succeeded */
return;
}
This pattern is problematic when undoA() is nontrivial, because it is duplicated in the code: a very common bug pattern occurs when only one of them is updated but the other one is missed. This is the underlying reason why in the Linux kernel the goto-based error recovery pattern is used (especially when any kind of locking is involved; multiple concurrent locks are notoriously easy to mess up) instead of duplicating the cleanup cases: the duplicates way too often fall out of sync during maintenance.
Religiously avoiding goto is at least as stupid as using it when it is not necessary. Don't trust any rule of thumb so far as to claim it always applies; they never do.
The other pattern to avoid goto is to use a separate state variable. I've shown an example of that in the thread Picuino linked to, related to selective cleanup (https://www.eevblog.com/forum/general-computing/is-it-a-good-idea-to-use-goto-statement/msg3081386/#msg3081386). Because this pattern tracks the cleanup needs using a separate variable, it has its own cognitive cost for us humans, and may not always be superior to a well-done goto pattern.
-
This pattern is problematic when undoA() is nontrivial, because it is duplicated in the code: a very common bug pattern occurs when only one of them is updated but the other one is missed. This is the underlying reason why in the Linux kernel the goto-based error recovery pattern is used (especially when any kind of locking is involved; multiple concurrent locks are notoriously easy to mess up) instead of duplicating the cleanup cases: the duplicates way too often fall out of sync during maintenance.
Religiously avoiding goto is at least as stupid as using it when it is not necessary. Don't trust any rule of thumb so far as to claim it always applies; they never do.
The other pattern to avoid goto is to use a separate state variable. I've shown an example of that in the thread Picuino linked to, related to selective cleanup (https://www.eevblog.com/forum/general-computing/is-it-a-good-idea-to-use-goto-statement/msg3081386/#msg3081386). Because this pattern tracks the cleanup needs using a separate variable, it has its own cognitive cost for us humans, and may not always be superior to a well-done goto pattern.
When I asked for an example where goto is truly necessary, I expected someone to bring up a case with a complex, tangled algorithm where execution needs to break out of deeply nested loops in an unexpected way. However, as I mentioned earlier, this is not a justification for why goto is necessary. On the contrary, it’s an indication that there are serious structural problems in your code flow. In such cases, the right approach is not to use goto, but to refactor your code - decomposing it properly, separating resource allocation/deallocation from the core algorithmic logic, and structuring it in a way that eliminates the risk of improper cleanup.
That being said, properly refactoring code is not always easy. It can require significant experience to write simple, clean, and maintainable code. But that doesn’t mean goto is justified - it just means refactoring takes effort.
Regarding the use of goto in the Linux kernel: some projects indeed have less strict policies and tolerate such patterns as long as they are not abused. After all, if the Linux kernel crashes, it's usually not catastrophic - it’s an inconvenience that leads to bug reports, but it doesn't necessarily cause severe harm. However, there are projects where the policies are far stricter and strictly regulated. In such environments, not only are these kinds of mistakes unacceptable, but measures are actively taken to prevent situations where they could even occur. Different projects have different levels of tolerance for bad practices. If a bug on a web page is barely noticed and a Linux kernel crash is just an annoyance, there are also projects where mistakes can cost lives or have severe consequences.
This is why in some projects, shitty-code is not restricted at all, in others it is tolerated within limits, and in some, it is absolutely unacceptable.
Ultimately, no one can forbid you from using goto in your projects. However, it is important to understand that by doing so, you are introducing poor quality shitty-code, and you should be aware of the potential consequences that may arise from it.
-
Redundancy and monitoring are often used in projects that require so much security.
4 computers in the Shuttle: https://www.nasa.gov/history/sts1/pages/computer.html (https://www.nasa.gov/history/sts1/pages/computer.html)
On the Shuttle, four identical AP-101Bs would function simultaneously as a quadruple-redundant set during critical mission phases such as ascent and reentry, processing the same information, derived from completely separate data buses, in precise synchronization. If a conflict arose among the four primary computers, the majority§ would rule, voting the conflicting unit out of the loop. None of the computers, singly or en masse, could turn off any otherthat step was left to the crew. An errant machine would announce itself to the crew with warning lights, audio signals, and display-screen messagesall suggesting that the crew might want to isolate (i.e.; turn off) the offending computer from the system.
EDIT:
There are also examples of Linux used in safety-critical environments: https://elisa.tech/ (https://elisa.tech/)
-
Ultimately, no one can forbid you from using goto in your projects. However, it is important to understand that by doing so, you are introducing poor quality shitty-code, and you should be aware of the potential consequences that may arise from it.
:-DD No, that's just your misunderstanding, confusing bad uses of a tool for the tool itself, and therefore labeling the tool bad. Your viewpoint is utterly simplistic, and therefore ridiculous.
If you knew anything about maintainable code or avoiding bugs, you'd know that the Linux kernel has much lower bug density compared to any enterprise code. Your own company, even if producing code used for critical life-sustaining equipment, almost certainly has a higher bug density; the only way you're not mired in lawsuits is a strict review and testing cycle (or clients that just don't notice or know any better). Labeling certain tools as "shitty" and "poor quality" is just their way of trying to wrangle lower-quality developers like yourself into producing something that can be shipped after sufficiently rigorous testing and review.
No matter how much you repeat it and try to convince yourself and others of it, goto does not automatically make for shitty code. In the error-case cleanup paths, it is superior to the case you claimed is better, because it does not duplicate code and lead to maintenance-related bugs (one copy updated, the other not updated, and because they are no longer identical, reviewers not catching the discrepancy). No matter of labeling it "shitty" makes it worse and yours better, because the real world shows your dogma just doesn't hold.
It seems to me you lack the skill and the experience to discuss these matters, so perhaps you should leave it to those who do.
Redundancy and monitoring are often used in projects that require so much security.
For hardware, not for software. The units run the same code.
-
:-DD No, that's just your misunderstanding, confusing bad uses of a tool for the tool itself, and therefore labeling the tool bad. Your viewpoint is utterly simplistic, and therefore ridiculous.
If you knew anything about maintainable code or avoiding bugs, you'd know that the Linux kernel has much lower bug density compared to any enterprise code. Your own company, even if producing code used for critical life-sustaining equipment, almost certainly has a higher bug density; the only way you're not mired in lawsuits is a strict review and testing cycle (or clients that just don't notice or know any better). Labeling certain tools as "shitty" and "poor quality" is just their way of trying to wrangle lower-quality developers like yourself into producing something that can be shipped after sufficiently rigorous testing and review.
Having worked on medical device projects that undergo regular testing and audits, I can confidently say that, compared to the level of rigor I have observed in such environments, the Linux kernel is a mess of poorly structured code with numerous bugs. However, this is not to say that Linux is inherently bad or mismanaged - I fully recognize that it is a free, community-driven project that lacks the level of funding necessary to enforce strict development practices. In fact, considering these constraints, I’d say it is holding up remarkably well, and I genuinely appreciate its development. That said, comparing it to large-scale commercial projects with significantly stricter methodologies and regulatory requirements would simply be incorrect.
Therefore, I find it quite surprising to hear you claim that Linux has fewer bugs, when my own experience shows the exact opposite. Your response makes it quite evident that you have never worked on projects with strict regulatory requirements, where coding standards are significantly more rigorous than in typical software companies.
Comparing bug density in the Linux kernel to enterprise software is meaningless without context. The Linux kernel is developed under an open-source model with thousands of contributors, strict code reviews, and an extensive testing process - yet even then, issues still arise. In contrast, projects in regulated industries, such as aviation, medical, or automotive safety systems, operate under even stricter constraints, where certain coding practices - including the use of goto - are outright prohibited due to their potential to introduce hard-to-trace errors.
Dismissing coding guidelines as mere attempts to "wrangle lower-quality developers" only shows a lack of understanding of how high-assurance software is built. In environments where failures can cost lives, health or big money, best practices exist for a reason - namely, to minimize risk and enforce maintainability at a level that goes far beyond what is acceptable in general-purpose software.
No matter how much you repeat it and try to convince yourself and others of it, goto does not automatically make for shitty code. In the error-case cleanup paths, it is superior to the case you claimed is better, because it does not duplicate code and lead to maintenance-related bugs (one copy updated, the other not updated, and because they are no longer identical, reviewers not catching the discrepancy). No matter of labeling it "shitty" makes it worse and yours better, because the real world shows your dogma just doesn't hold.
I completely disagree with your claim that goto ensures "superior" resource cleanup ways and eliminates errors related to incorrect exits from nested loops or improper resource deallocation. On the contrary, using goto makes such mistakes possible and, worse, hidden during compilation and code review.
A compiler will never be able to detect that you skipped an essential cleanup block that should have been executed during an early exit from an inner loop - because goto does not enforce any constraints in this regard. And a person reviewing your code might simply overlook the issue due to the spaghetti-like structure that goto introduces.
Simply put, goto allows you to jump almost anywhere, and the compiler won’t flag it as an issue. This lack of proper checking is the real problem.
This is precisely why using goto does automatically turn your code into shitty code - not because someone keeps repeating it or personally believes so, but because it objectively makes errors harder to detect and trace at both the compilation and review stages. Furthermore, in the event of a critical incident caused by software failure, analyzing and identifying the root cause becomes significantly more difficult when control flow is obscured by goto statements. Investigations in high-stakes environments, such as medical devices or safety-critical systems, require clear, predictable execution paths to efficiently diagnose and address failures. Code that relies on goto introduces unnecessary complexity, making such investigations more time-consuming and error-prone, which is simply unacceptable in industries where failures can have severe real-world consequences.
A straightforward example can be seen in the code provided by the topic starter, which is riddled with labels and goto statements to the point that even its own author struggles to understand it. I have had to analyze similar code in the past to determine its behavior, and while I could reconstruct its logic and rewrite it in a structured manner, the reality is that such code is shitty code - difficult to work with, requiring excessive time and effort for analysis. It’s tedious, error-prone, and unnecessarily complex, which is exactly why I have no desire to deal with it.
If you believe that goto somehow makes code more reliable, I encourage you to try to rewrite his code yourself. You’ll quickly realize firsthand why I categorize it as shitty code. ;)
It seems to me you lack the skill and the experience to discuss these matters, so perhaps you should leave it to those who do.
Your assumption is incorrect. I have spent more than decade working on medical device projects, where strict regulations, rigorous audits, and high safety standards are mandatory. In such environments, code quality is not a matter of personal preference but a strict requirement - far beyond what is typically enforced in general software development.
Given this experience, I find it quite ironic that you suggest I lack the skill or expertise to discuss these matters. If anything, your repeated reliance on goto as a "solution" to resource management issues suggests a lack of familiarity with structured programming principles and best practices in high-reliability systems. Perhaps instead of dismissing opposing viewpoints, you should consider that there are industries where your approach would not meet the necessary standards for safety, maintainability and regulatory requirements.
If you don't believe me, you can read other sources, for example you can read this article:
https://web.eecs.umich.edu/~imarkov/10rules.pdf
Especially the first rule in the list:
Rule 1: Restrict all code to very simple control flow constructs - do not use goto statements, setjmp or longjmp
constructs, or direct or indirect recursion.
-
Having worked on medical device projects that undergo regular testing and audits
Maybe as an intern, perhaps. Other than that, I think you're full of shit, with nothing to back up your claims, except parroting "rules" you've heard from others.
-
Maybe as an intern, perhaps.
I understand that you might question my experience, but just to clarify, I joined my first company working with medical devices as a mid-level developer and grow to Senior Software Engineer. Prior to that, I worked as a Lead Developer in a company focused on industrial smart sensors for pressure, temperature, and gas metering devices used in large gas pipelines. I developed firmware for industrial sensors and meters, which could be seen as an equivalent to Honeywell products, although the company was local. I independently developed the firmware from scratch, including conducting tests, research, and selecting algorithms for temperature compensation, calibration, and more. I also participated in the certification of finished devices and the deployment of the first units at the company’s facilities. The firmware ran on MSP430 (MSP430F149 if I remember correctly) under an RTOS kernel, which I ported by himself to the MSP430 platform. Almost all of the firmware code was written by me from scratch. Some of the temperature compensation algorithms were suggested to me by an acquaintance who had worked on pressure sensors designed for high-temperature conditions (>700°C). I simplified and refined these algorithms. The calibration algorithms were recommended by someone who had previously worked in the production of Soviet nuclear missiles. According to his stories, he had worked on inertial navigation systems development. He also shared tales about how the KGB would arrive for product acceptance inspections, and based on his accounts, there were areas even back then where the engineering standards were exceptionally strict. :)
Back then, I had to do more than just write code - I spent days next to a thermal chamber with a pressure compressor, recording sensor characteristics under various temperature and pressure conditions and then analyzing the data. I was also involved in the development of the measurement circuitry, specifically the ADC-related aspects. However, the primary circuit design was handled by another engineer; I mainly suggested different ADC configurations, which he then prototyped, and we tested them together. The main challenge in measurement was achieving high accuracy across a wide temperature range from -60 to +80 degrees Celsius. Sensor readings were highly temperature-dependent, with the pressure sensor being particularly sensitive to temperature variations.
Later, I transitioned to another medical devices company directly as a Senior Software Engineer. Additionally, if you are interested in my experience with C, I started learning it in school before attending university, at about 12 years old (first on HI-SOFT C on ZX Spectrum and later on IBM PC). In fact, even before university, I wrote my own UI in C++ for an EEPROM programmer using the Borland Turbo Vision library. I started learning Basic and Z80 assembly around the age of 10 (it was on ZX Spectrum). My interest in electronics began around the age of 7, and by 8, I had already soldered my first radio receiver. :)
One of the medical devices companies I worked for is in the top 10 of the Fortune 500 list. The second is a less well-known US company, but its medical electronic equipment is also quite widespread worldwide. The third company is also a relatively lesser-known US firm, but it has offices and operates globally, including in the US, EU, Israel, and many other countries. It is well-known in the medical field and among healthcare manufacturers, although its name may not be familiar to the general public.
In all medical device companies I worked for, my position was Senior Software Engineer. I am not an intern. Interns are typically hired from a pool of less experienced individuals with a commitment to work exclusively for the company. Instead, I am the type of engineer hired to lead and contribute to new projects, to kick-start new initiatives, or to rescue projects that are struggling due to an overabundance of internal personnel. Interns are usually not capable of handling such responsibilities, if that is what you meant by referring to interns.
May I ask about your experience? I'm curious to know what background you bring to the discussion?
Other than that, I think you're full of shit, with nothing to back up your claims, except parroting "rules" you've heard from others.
I understand that you disagree with my points, but resorting to personal insults isn't productive or helpful to the discussion. Perhaps there is a generational gap between us that is causing a difference in perspective, but I don't believe that young approach of insulting others adds any value to the conversation or reflects well on you. I would prefer to continue our discussion in a more constructive and respectful manner.
My point of view has already been confirmed by the original poster, who provided an example of code using goto. As you can see it almost non-readable. Additionally, despite several attempts to provide examples where goto allegedly seems necessary, I presented equivalent code examples that do not require goto. I also provided an example of guidelines from NASA, which state the same - avoid using goto. Don't you think that the evidence supporting my position is more than sufficient, and that you're simply choosing to disregard it?
In my view, this is sufficient evidence. What further proof would you require to back up my claims?
Indeed, every company has its own set of rules and regulations, and as professionals, we are obligated to adhere to them. In more serious organizations, these rules can be quite strict, but I don't see anything wrong with that. These guidelines are established to ensure the production of high-quality code, and they are based on experience rather than arbitrary decisions. They are developed through careful analysis and real-world experience, and following them is essential for maintaining standards and consistency. Over time, as you gain more experience, you’ll realize that these rules are not there to hinder you, but rather to guide you toward writing better, more reliable code.
-
@Nominal Animal, You remind me of another user on this forum who tried to convince me that he was a seasoned professional with extensive experience, while claiming that I didn't understand anything and that I'm talking complete bullshit. The irony was that he portrayed himself as an expert on a program I had actually written, yet he was unaware of that fact. It was quite amusing. :D
Subsequently, I came across other messages from that user, and I was rather disappointed to find that he had a poor understanding of the topic and lacked even basic knowledge. Yet, for some reason, he resorted to insulting me. Given that, as I remember, you are well-versed in digital filters (isn't it?), it's somewhat surprising to see a similar approach with insults coming from you.
-
In structured programming you can ALWAYS replace goto with other operations.
"The fact that it is possible to push a pea up a mountain with your nose does not mean that this is a sensible way of getting it there" - Chris Strachey.
-
In structured programming you can ALWAYS replace goto with other operations.
"The fact that it is possible to push a pea up a mountain with your nose does not mean that this is a sensible way of getting it there" - Chris Strachey.
I prefer "It is possible to cross the Alps on a bicycle, but that doesn't mean it is a sensible way of travelling" :)
-
I prefer "It is possible to cross the Alps on a bicycle, but that doesn't mean it is a sensible way of travelling" :)
Drifting a bit off topic but my dad did actually cross the Alps on a bicycle (meaning cycled on roads through the Alps, not up and down mountainsides) as part of some enthusiastic youth sporting nature thing (https://en.wikipedia.org/wiki/Friends_of_Nature). He apparently quite enjoyed it.
-
I prefer "It is possible to cross the Alps on a bicycle, but that doesn't mean it is a sensible way of travelling" :)
Drifting a bit off topic but my dad did actually cross the Alps on a bicycle (meaning cycled on roads through the Alps, not up and down mountainsides) as part of some enthusiastic youth sporting nature thing (https://en.wikipedia.org/wiki/Friends_of_Nature). He apparently quite enjoyed it.
I've walked across parts of the Dolomites, including the old commercial "Bread Trail", i.e. the Viel Di Pan. Definitely a "fit for purpose" transportation mode, since the purpose was "memorable fun challenging holiday".
-
There is a nice book about this kind of adventure
-
Religiously avoiding goto is at least as stupid as using it when it is not necessary.
Don't trust any rule of thumb so far as to claim it always applies; they never do.
The DO178B level A-D integrated with avionics rules strictly prohibits any use of "goto" for everything except "critical sections", which are - by definition - considered "low level", therfore all documents and testing methods require special activities, which are known, well tested; the point is that, being special, they require many more hours both from the testing team and from the QA team, and this for each iteration between development and testing, therefore for each revision.
It is therefore a question of "how much does it cost" to have a "goto", rather than replacing it with something else, which does NOT require special procedures.
There are always Critical sessions in RT operating systems(1), so having a goto in those sessions does not add much more cost.
But if you put "gotos", say ... in the application layers (where it should be avoided), then you need to provide a special testing activity just for that goto.
So, it can also be seen as a question of costs :-//
edit:
(1) e.g. WxWorks-RT is certified for DO178B-levelA, it can be used in supersonic aircraft traveling >= 1,193.76 km/h.
It uses "goto" in a few critical sections. Only a few sections, but testing and QA of these special sections requires "4 times +1" more effort from both the testing team (x2 effort) and QA team(x2 effort) than the rest, plus manual inspection and approval from seniors(+1 effort).
-
In MISRA-C, the use of goto is not prohibited entirely, but must be restricted to only one exit point in a given construct (function or loop). And it's not just with 'goto', but also with 'break'.
So, in a loop, you can only use a single break. The idea is to have a single point of exit inside a loop, apart from its normal condition.
Which already allows two different termination conditions. With some stricter rules, a single termination condition is required.
Sometimes those rules can be clunky to respect, but they are not stupid either. Invariants are much easier to verify if you don't have tons of conditional exits all over the place.
But clunky this can be. Say, you have a sequence of statements that can return an error. Enforcing a single point of exit in this case it very inconvenient, at least with usual languages.
-
The DO178B level A-D integrated with avionics rules strictly prohibits any use of "goto" for everything except "critical sections", which are - by definition - considered "low level", therfore all documents and testing methods require special activities, which are known, well tested; the point is that, being special, they require many more hours both from the testing team and from the QA team, and this for each iteration between development and testing, therefore for each revision.
Exactly. These rules in DO178B and MISRA-C do not magically cause bugs to not occur; they simply make it easier to catch problems in testing and QA review.
Simply put, the subset of C these safety standards specify is not "bug-free" or the non-"crappy" parts of C; it is the subset that existing tools and procedures can review and verify effectively. They are all about the process of safety-critical product development, using less than perfect developers (i.e. humans).
For minimal bug density C code, go take a look at Dan J. Bernstein's projects (https://cr.yp.to/).
(1) e.g. WxWorks-RT is certified for DO178B-levelA, it can be used in supersonic aircraft traveling >= 1,193.76 km/h.
It uses "goto" in a few critical sections. Only a few sections, but testing and QA of these special sections requires "4 times +1" more effort from both the testing team (x2 effort) and QA team(x2 effort) than the rest, plus manual inspection and approval from seniors(+1 effort).
Exactly. A very good example of how goto is an useful tool if carefully and selectively applied. The problem is not in goto itself, but in how most developers use it, leading to a "rule of thumb" saying that "using goto is always bad".
Based on a quick grep over my test case archive, I use goto in fewer than one project in hundred. (I didn't bother to check how often in those rare cases I use computed gotos, a GNU extension, though; it can make certain complex state machine structures much simpler to maintain without introducing new bugs.)
Sometimes those rules can be clunky to respect, but they are not stupid either. Invariants are much easier to verify if you don't have tons of conditional exits all over the place.
Sure; but, it is important for anyone developing safety-critical systems to understand that these rules are about the development process, to be utilized when you do have the test and review QA procedures in place; they do not magically make for better code.
It is perfectly exemplified by the fact that both MISRA-C and DO178B have exception clauses and procedures set for when the simplified subset of C just isn't the appropriate tool. They do not say "goto always leads to buggy code", they say "use goto and other constructs sparingly, because they make the required testing and QA more difficult".
I would go even further –– and DiTBho can comment on this, because they developed their myC variant of C for these purposes exactly –– and claim that even if you write MISRA-C or DO178B -compliant C from the get go, it does not really reduce the number of bugs and issues in the code; it only makes testing and QA review easier. That is, if you do not do the testing and review cycles, and simply trust that being MISRA-C or DO178B compliant makes for better code and fewer bugs, you will be sorely disappointed.
That is also the reason why Ada/Spark is often used for safety-critical code: it is designed to allow automated correctness verification (logical soundness, verifiability, bounded resource use). It is slightly harder to reach the same performance as C, but much more of the review and verification process can be automated.
I just cannot understand how anyone non-stupid could extrapolate "goto is always bad and must not be used" from all of this.
-
I would go even further –– and DiTBho can comment on this, because they developed their myC variant of C for these purposes exactly –– and claim that even if you write MISRA-C or DO178B -compliant C from the get go, it does not really reduce the number of bugs and issues in the code; it only makes testing and QA review easier. That is, if you do not do the testing and review cycles, and simply trust that being MISRA-C or DO178B compliant makes for better code and fewer bugs, you will be sorely disappointed.
Yup, precisely, it only makes testing and QA review easier.
It must also be said that for each activity a lot of documents must be prepared, many of which involve testing activities, both manual and automatic.
Automatic activities are faster and less "boring" than manual ones, and require less effort, but they require greater "observability" of the code.
So it is good, also for this reason, to write the code in a certain way, to simplify your life later in the testing activities, and to simplify the life later in QA activities.
-
To be very clear: I fully agree that following MISRA-C or DO178B will result in a better end product. I am only saying that labeling certain features like goto to always lead to crappy code is absolutely untrue; as is following a subset of MISRA-C or DO178B process and believing the end result is "almost" as good as if one were to follow the full process as outlined in said standards.
Those standards are not about picking only the best in the programming language; they are about the entire process, and using a subset of the programming language that allows the most efficient and process-friendly subset of said language.
There is a big difference in the process of developing safety-critical code, and in writing robust, reliable, minimally-buggy code. Neither involves labeling some C language features as always leading to crappy buggy code; they are both all –– and only! –– about a proper engineering approach to software development. You just cannot distill that into always-correct rules of thumb or dogmatic avoidance of language features. I'm not saying to use goto whenever you feel like it, either: I use it exceedingly rarely, because I only use it whenever it is appropriate.
Offhand, I know of only one language feature that always leads to crap, and that was the Magic Quotes feature in PHP. And even that was more like a interpreter configuration than language feature. It was an early doomed attempt at making it easier for newbies to write "safe" PHP, by automagically escaping non-SQL-safe characters received from HTML forms.
-
To be very clear: I fully agree that following MISRA-C or DO178B will result in a better end product.
I really don't.
If you just follow them because it gives you a feeling of quality, without thinking about any quality assurance process, all bets are off. Some of the rules are slightly good; others (like full ban of goto or function pointers) potentially make for slightly worse (less maintainable, less readable, so more prone to bugs) code in some cases, but not always, and not for every developer - these rules could also prevent abuse of said constructs.
Knowing you are writing "MISRA code" could also drive you to false sense of security, a well known phenomenon, then again it's also an overdiagnosed phenomenon by kitchen sink failure analysts, so really, dunno :-//
Typical example of this would be a company like ST, known from producing totally random crap software, suddenly making a statement that their code is MISRA compliant. Of course it's still as buggy as ever, with zero documentation and absolutely zero consistency and zero design, just something ad hoc summer trainee crap held together with bubble gum. In a process like this, there is a real risk that new bugs are added when the new summer trainee is hired to modify all code to be "MISRA compliant" for pure marketing purposes. But I don't know how common this is. Maybe I'm exaggerating the risk.
And then again, if you do implement rigorous quality processes, like (hopefully) any company operating in aviation... I'm 100% certain your product quality would be top-notch even if you didn't use MISRA.
So I believe things like MISRA make only very small difference in the big picture, if any. Probably bigger quality gains can be had by having programmers read the rules carefully and think about them, even if they are not forced to follow them strictly.
But the real aim for MISRA & co is clear. You said it already but I'm going to repeat it: it is obviously easier to analyze code flow automatically and manually, when number and types of code flow affecting constructs is limited (goto, function pointers). The critical question however is, what does it do on the big picture? That function pointer was (hopefully) introduced by a developer to reduce repetition, copy-pasting, or complicated if-else conditional mess. Copy-pasted repeated if-else mess might be easier to analyze for a machine, so if you compare the implementation against a machine-readable specification to do formal verification, then that's a win. But is this relevant for most projects people think about? If you just introduce MISRA and think that this now gives you aviation quality code, without introducing the formal verification that needs to go with it, you just introduced new sources of bugs from ignoring patterns like DRY, well known to improve quality outside of fields like aviation.
-
To be very clear: I fully agree that following MISRA-C or DO178B will result in a better end product.
If you just follow them because it gives you a feeling of quality, without thinking about any quality assurance process, all bets are off.
Absolutely –– but I meant that if you follow them fully, including the review and QA processes –– then the end result will be better. They specify the product development process, not a subset of C to use to get better results.
Taking just a small part, say the subset of C these standards define, gets you absolutely nowhere (except for delusions). These standards are about the entire process: a framework you work in, not a set of useful ideas you can pick and choose and be good.
So I believe things like MISRA make only very small difference in the big picture, if any.
For individual programmers working alone, they give very little, unless you delve very deep into the very process like DiTBho described wrt. DO178B and "myC", and emphasizing the documentation and review steps needed to actually fulfill the ideas behind those standards. If I've understood correctly, the entire "myC" idea was to subset-and-extend C to better fit the entire process, specifically debug/review/verification. (Do firmly point it out if I've misunderstood its purpose, DiTBho!)
Neither MISRA-C nor DO178B should be considered a "programming language standard" at all. They are about the full development process, with the subset of C chosen to fit that process. They don't work when you work alone; they're organizational process standards.
I claim that statements like ST declaring their code to be "MISRA-C compatible" is just marketing wank, and means basically nothing. It is like declaring oneself to be vegan, because the meat one consumes is all from herbivorous animals. It is picking one detail, and pretending it is the main point in an effort to try and mislead others. For an organization, it means they'll still have to do the entire testing-review-QA cycle –– and knowing ST's code quality as shown online, will have to rewrite most of it to actually pass and satisfy the present needs.
If you just introduce MISRA and think that this now gives you aviation quality code, without introducing the formal verification that needs to go with it, you just introduced new sources of bugs from ignoring patterns like DRY, well known to improve quality outside of fields like aviation.
Yes, exactly. Or, conversely, that limiting oneself to the subset defined in MISRA-C or DO178B somehow magically makes oneself produce better code.
The methodology or approach to write better code in the first place is usually called software engineering, because you apply the same engineering principles to software development as you do when designing larger systems with lots of components.
To circle back to the topic at hand, converting machine code or assembly to C, the simple answer is that you don't.
What you do, is convert the machine code to any intermediate form or programming language that makes it easier for you to decipher its operation and the intent of the original developer(s). You write a detailed description of it, either formally (recommended if group effort) or commenting the intermediate language (only valid if doing this alone or with a coding buddy). Ghidra and other tools can be quite useful here.
I like to follow that up by creating a limited simulated environment where I can implement parts/subsystems in my preferred programming language, and compare its outputs to the original outputs from the same inputs. I do this for individual modules. After I have sufficient modules, I start looking at their interactions, and trying to understand how the developer approached the overall problem.
When you have verified you have a full understanding of the operation of the system at hand, you reimplement it. You don't convert the code; you write new code that fulfills the same requirements. You use the old code to inform you of the possible approaches, but as long as you note all the side effects and interactions, you don't need to do it the exact same way; it suffices that all intentional side effects and results match.
For myself, I don't mind if the intermediate form of the new code contains gotos, because I know from experience that when the rewrite/reimplementation behaves like the original, I'll still want to refactor the key parts of the code to be maintainable. I do not have the brainpower to think about long-term maintenance when I first rewrite code from one language to another; I need to sleep in between to see the code with fresh eyes and shift focus. It is at least 99% likely that I'd replace those goto structures with subfunctions, switch statements, do..while or while "loops", et cetera.
Splitting even this process into sub-steps makes it much more manageable. Even by rereading this thread we can see that starting with an intermediate representation of the machine code (including clunky constructs like gotos and labels scattered everywhere), and then rewriting these using easier to maintain patterns, is the way to go. However, do not forget that you will forget the intention/purpose of each function and chunk of code in a few weeks. You will definitely want to write comments or descriptions of your understanding of the purpose or developer intent of each function. What the functions do is easy to see in the code, but that intent is what makes it possible to consider whether what the code does is correct or not. If you don't have or remember that intent, you'll have to try and rediscover it, as otherwise you can only fix obvious typos (like off by one errors), and not any misunderstandings of what the purpose of the intent of the original code was.
-
I'd say about half of the rules in those guidelines is "common sense" and relatively sane and the other half is extreme to various degrees and indeed made to accomodate large teams of developers while ensuring a reasonably common code style and avoiding constructs and language features that are known to be "slippery", making the code easier to review and easier to test.
Of course that doesn't mean the output will be automatically of good quality, and sure enough, it can be misused and lead to the problem of "programming to just pass the automatic static analysis checks" (which indeed I suspect is what ST devs mostly do).
Certainly far from ideal, but OTOH managing software projects, when any kind of reliability and safety is involved, is extremely difficult, in particular when your team exceeds about 2 developers. So, yeah.
-
like DiTBho described wrt. DO178B and "myC", and emphasizing the documentation and review steps needed to actually fulfill the ideas behind those standards. If I've understood correctly, the entire "myC" idea was to subset-and-extend C to better fit the entire process, specifically debug/review/verification.
That's correct, I think this is just one of the attempts made, but this is the direction that seems to provide significant help.
-
There is a nice book about this kind of adventure
There's also a book on doing it on foot, "Clear Waters Rising: A Mountain Walk Across Europe" by Nicholas Crane. Apparently the most important thing to have with you on such a journey is an umbrella.
And for a rather more exotic one, "A Short Walk in the Hindu Kush" by Eric Newby, who didn't take an umbrella.
Now... what were we arguing about again?
-
For minimal bug density C code, go take a look at Dan J. Bernstein's projects (https://cr.yp.to/).
Or Wietse Venema. Or a couple of other people who work in the security field. I don't know Dan's coding process but some of the others combine both very careful coding with a large amount of auditing and checking, with the result that some of their code has had essentially zero security vulnerabilities despite intensive third-party attempts to find some. That's a pretty impressive feat when you consider other security products out there, one-person projects beating ones created by multimillion-dollar companies with vast resources.
-
Based on a quick grep over my test case archive, I use goto in fewer than one project in hundred. (I didn't bother to check how often in those rare cases I use computed gotos, a GNU extension, though; it can make certain complex state machine structures much simpler to maintain without introducing new bugs.)
That's exactly where I use it, from an equally quick grep, there's a somewhat complex state machine that has to pop up from various levels of nesting and go to a common cleanup/reset section, followed by the next-state step in a while loop. Every other way to do this without gotos, and I'd tried several, is much, much uglier and more confusing.
Maybe that'd be a good design rule, "do not use a goto unless the alternatives are much uglier and more confusing". However that's a bit subjective, failing that the MISRA rules are generally good enough.
-
There is a nice book about this kind of adventure
There's also a book on doing it on foot, "Clear Waters Rising: A Mountain Walk Across Europe" by Nicholas Crane. Apparently the most important thing to have with you on such a journey is an umbrella.
And for a rather more exotic one, "A Short Walk in the Hindu Kush" by Eric Newby, who didn't take an umbrella.
Crane also wrote about cycling in the Himalayas and has made TV programmes, Dervla Murphy left her small town for the first time - and cycled to India in the winter of '63.
I find Newby boring, but his weird chance meeting with Wilfred Thesiger is memorable. I had something similar happen on top of a 10kft mountain in the Dolomites.
All in all there are some similarities between walking across the Alps and reversing machine code into C; both are pretty pointless unless you do them "because it is there".
-
I think Newby wasn't necessarily boring but more oversold somewhat, it's not really the epitome of humourous Englishness or whatever. That honour goes to Three Men in a Boat, but you have to read it in the original German.
-
On the other hand...
Disadvantages of goto in C
I didn't ask for copy-pasted quotes from some online article.
I asked a simple and specific question - can you provide an example where goto is truly necessary and cannot be replaced with conventional structured code that avoids goto? Do you have one?
Articles are written by people like everyone else, and people make mistakes. That's why you should think for yourself instead of blindly relying on something just because someone wrote it on the internet.
This does not exist. In structured programming you can ALWAYS replace goto with other operations.
Well. I'm glad you finally admitted it. :)
We can only talk about where goto may be more effective than other solutions. And as you rightly pointed out, goto can probably be more effective but at the same time more insecure and error prone.
Are you serious? What makes you think that avoiding goto leads to more insecure and error-prone code? :o
Doesn't the example provided by the topic author clearly demonstrate that using goto results in code that even the original author struggles to understand? Do you really consider that to be more secure and less error-prone than straightforward, readable code, where the author fully understands what they are doing and which can be easily reviewed and analyzed for errors?
That's not what he? said.
He? meant that `goto` is error-prone.
Read carefully, then reply.
-
That's not what he? said.
He? meant that `goto` is error-prone.
Read carefully, then reply.
You're right, that was my mistake. I initially thought this should be obvious to everyone, but judging from your comment, not everyone saw it that way. Then there is a sense to clarify this.
I misinterpreted @Picuino sentence due to a combination of factors - the phrase contains a contrast ("but at the same time"), I read that part quickly, and English is not my native language. As a result, I initially thought it was saying that avoiding goto leads to more insecure and error-prone code, while in reality, it meant that goto itself is more error-prone. Thanks for the clarification. So there’s no real disagreement between me and @Picuino regarding the risks of using goto. For this reason, I’m withdrawing my question to @Picuino, as it became clear after his response.
-
I never use the goto statement in C language. But it is not for a religious reason, actually goto is present in many C statements like break, continue or return.
I once read that goto was not as evil as one might think according to the widespread opinion in structured programming. I did some research and came across structures like the one I posted earlier that use goto for resource release.
It is true that the alternative option you posted (@radiolistener) is perfectly valid and does not use goto, but it repeats code at several points and that is also a source of errors.
void foo()
{
if (!doA())
goto exit;
if (!doB())
goto cleanupA;
if (!doC())
goto cleanupB;
/* everything has succeeded */
return;
cleanupB:
undoB();
cleanupA:
undoA();
exit:
return;
}
what is the reason for goto in your example?
Here equivalent code but with no goto:
void foo() {
if (!doA()) {
return;
}
if (!doB()) {
undoA();
return;
}
if (!doC()) {
undoB();
undoA();
return;
}
/* everything has succeeded */
return;
}
As you can see, its much easier to read and support. And there is no need to use goto at all.
-
Just as a curiosity. A BASIC program and their spaghetti goto structure that can generate mazes.
https://www.quora.com/Whats-wrong-with-goto-statements (https://www.quora.com/Whats-wrong-with-goto-statements)
-
If you read old BASIC listings then it's obvious where the "goto considered harmful" mindset is coming from.
It is very rare to see anything similar in C, though. The culture of structured programming just begins from first textbook examples, tutorials and so on.
I remember as a kid writing a C program something similar to that BASIC example: it was a rudimentary chat / file transfer utility for dial-up modems, on DOS, and IIRC it was a few thousand LoC in main() with tens if not hundreds of gotos. But I was like 12 years old at the time. Such horrible practices are self-weeding; writing, reading and maintaining such mess is so horrible that anyone starts thinking, "there must be a better way". And then they discover loops, function calls and so on. I don't remember writing something like that ever again.
What I'm surprised at is that almost no one has nothing bad to say about continue and break. Yet, they do the same as goto, transfer the control flow to somewhere else bypassing loop conditions, and in some ways they are much worse than goto: with goto you have the label so there is no question where the flow goes to; with break, the flow jumps to some }, usually not the next one; sometimes the next-after-next but not always even that. To see where the flow jumps to, you scan for } forward but then for each } you look backward what the matching keyword for the block is, and only if it's for or while or do then the matching } is an effective destination for break. How convoluted.
Doing double-breaks with temporary variables multiplies that confusion. A lot of surface area of errors: you can first mis-identify the } where the first break jumps to; then you can make a mistake with how you set and compare the temporary flag; and then you can mis-identify the } where the second break jumps to. Also there is a risk of doing something in the loop body which you wanted to skip when the termination condition occurred, so you need to guard some non-related code with extra if or be careful with ordering of breaks and normal code...
Also doing a dynamic loop condition is... scary. I mean, something like, for(int i=0; i < terminated ? x : y; i++)
goto TERMINATE_LOOP;
would have solved all that with, by far, least surface area for mistakes.
But, obfuscated code is nothing new. When "goto considered harmful" cultists are delivered with arguments like in this post, they never succeed shooting them down, because the real world facts are so convincing. Instead, they change into "it is possible to write code without goto" argument. Which is hilarious. You can avoid almost any construct. The question is, at what cost? Initial claim was avoiding it makes your code better. Revised claim is that it does not make your code that much worse. Hilarious, I repeat - but cults and religions usually are hilarious to outsiders.
-
Structured Programming with goto Statements
DONALD E. KNUTH
December 1974
https://pic.plover.com/knuth-GOTO.pdf (https://pic.plover.com/knuth-GOTO.pdf)
http://www.kohala.com/start/papers.others/knuth.dec74.html (http://www.kohala.com/start/papers.others/knuth.dec74.html)
-
And where was the poor OP in all this?
Staring in amazement at the TARDIS-sized can of worms he opened.
I think I'm going to take tggzzz's advice and "find another job".
-
And where was the poor OP in all this?
Staring in amazement at the TARDIS-sized can of worms he opened.
I think I'm going to take tggzzz's advice and "find another job".
That would be your decision based on what you can see on the ground.
As I've noted previously, Professor Eric Laithwaite at Imperial College used to set exams where one question was easy and sufficient get you a pass mark, one was more challenging and could get you a good degree, and one could not be answered adequately in the time available. He expected his undergraduate engineers to be able to determine which questions to avoid. If they couldn't, they wouldn't make good engineers anyway. I doubt he would be allowed to do that now, more's the pity.
The same is true when making a bid for a contract/sale. I've recommended "no bid" on several occasions.
Sometimes it helps to know why they are requesting reimplementation. Listen to what alternatives have been considered and rejected, and to the expected benefits of reimplementation. Work out how it will benefit their customers and why their customers will pay them more money for the same function. Sometimes marketing/sales people hallucinate a problem and/or a solution to the problem.
-
I never use the goto statement in C language. But it is not for a religious reason, actually goto is present in many C statements like break, continue or return.
While statements like break or if do affect control flow, they are much safer than goto. break only exits loops or switch statements, and if simply directs the flow based on conditions. Both have well-defined scopes, making them predictable and easy to follow. In contrast, goto can jump anywhere, leading to unpredictable and hard-to-maintain code. Therefore, break and if are not problematic, as they don’t allow arbitrary jumps like goto.
It’s not a matter of "religion" as some may suggest. The key difference is that goto can jump to arbitrary locations in code, making the program flow unpredictable and harder to maintain. On the other hand, statements like break, continue, and return have well-defined, limited scopes, which makes them more predictable and manageable. The concern with goto is its potential to create complex, hard-to-follow control flows, while other control statements like break and continue are structured and localized.
It is true that the alternative option you posted (@radiolistener) is perfectly valid and does not use goto, but it repeats code at several points and that is also a source of errors.
While using goto may seem like a more efficient solution by avoiding duplicated code, it actually leads to more problems in terms of code readability, maintainability, and flexibility.
In my approach, by utilizing explicit checks for resource cleanup, you can more easily manage and modify the logic for each exit path. It is true that there is some repetition, but modern compilers are capable of optimizing away this repetition, and worrying about such micro-optimizations is usually unnecessary. What is far more important is ensuring that the code remains clear, maintainable, and easy to extend in the future.
If you were to use goto, it becomes significantly more difficult to modify the cleanup logic. For instance, if you want to change the resource release behavior at a particular exit point, you'll have to create separate exit labels for each scenario (e.g., cleanupA, cleanupB, etc.). This quickly turns the code into a tangled mess, often referred to as "spaghetti code," which is much harder to read and maintain.
On the other hand, the approach without goto keeps the code linear and straightforward, with each condition clearly defined. It’s easy to change the resource release logic for any given exit condition without worrying about the structure of the entire flow.
In summary, while it might feel like goto reduces code duplication, it ultimately sacrifices readability and maintainability, which are far more important in the long run. A clean, easy-to-follow structure, even with some repetition, is a better investment for the future of your codebase.
And regarding micro-optimizations... Focusing on micro-optimizations often leads to the opposite of the intended result. By trying to manually optimize small aspects of the code, you may actually make it harder for the compiler to apply its own optimizations effectively. Compilers are highly optimized and can often generate much better, more efficient code than what developers might manually write. In many cases, attempting to optimize code at a micro level leads to slower, bulkier code because the compiler is no longer able to perform certain optimizations it would have done without the interference.
It’s generally better to focus on writing clean, maintainable code and let the compiler handle the optimizations. This approach often results in better performance and more manageable code in the long term.
-
And where was the poor OP in all this?
Staring in amazement at the TARDIS-sized can of worms he opened.
I think I'm going to take tggzzz's advice and "find another job".
It is clear that fighting with a spaghetti code to convert it into structured C code is a real torture.
It is easier and more gratifying to throw the whole project in the trash and start another one from scratch.
-
I think I'm going to take tggzzz's advice and "find another job".
If you're being forced to work with such poorly structured code, it might indeed be worth considering finding a better job. However, before making any decisions, it could also be worth exploring the possibility of refactoring the code from scratch, removing the reliance on goto and creating a more maintainable structure. To do this effectively, you'll need to fully understand the code's intended functionality and flow.
Starting fresh with a clearer design can not only improve the readability and maintainability of the code but also provide a valuable learning experience. In many cases, refactoring the code will make it much easier to work with in the long run and can lead to better results both for you and the team.
-
In contrast, goto can jump anywhere
Every idiot can keep repeating this like a broken record, but it does not become true. Try it. Scope of jumping with goto is pretty limited. You would know that if you either read the standard, any tutorial worth of its salt, or, simply, just tried it yourself.
You are thinking about something like setjmp/longjmp. Oh, wait, no. You are not thinking.
-
It is clear that fighting with a spaghetti code to convert it into structured C code is a real torture.
It is easier and more gratifying to throw the whole project in the trash and start another one from scratch.
Possibly. However, there is some silver lining with a relatively simple, imperative language like C: refactoring and improving the structure can usually happen piece-by-piece. It's not like everything being dependent on a perfect polymorphic object model.
In other words, just start identifying repeated functionality, and make them functions. Find places where code should be data instead, and create relevant data structures, and keep going.
"Spaghetti code" (a pretty loose term but most have some kind of rough idea what it means) feels bad, but it really isn't the worst crime one can do. A project cobbled together with copy-paste code, long functions, if-else messes and, say, a lot of gotos can be saved in the same way an elephant can be eaten.
I'm much more worried when I see seriously overengineered, in CS sense, cathedrals where you have no idea how the modules interact with each other. You will just find endless meta after meta; classes with no obvious functionality related to the actual project spread over thousands of small modules.
I mean, I take a single 10000 LoC C file goto mess any day over a 10000 C++ file project, or a ProblemFactoryFactoryFactory project. At least with the spaghetti mess, you can just start following the code from the beginning of main(), and some significantly non-zero % of the code tends to do something you know the application is doing.
And don't forget the Version 2 Syndrome. It's very real and a scary risk. If v1 exists and works, and the only problem is that some software engineers feel that it's written in poor coding style, and they suggest total rewrite, be very careful in decision making. They could be right. But history shows, that 95% of such rewrites end up massively overtime and overbudget and result in a new mess which then again is "in poor coding style" according to the next engineers.
-
Every idiot can keep repeating this like a broken record, but it does not become true. Try it. Scope of jumping with goto is pretty limited. You would know that if you either read the standard, any tutorial worth of its salt, or, simply, just tried it yourself.
You are thinking about something like setjmp/longjmp. Oh, wait, no. You are not thinking.
Resorting to insults doesn’t strengthen your argument - it only reflects poorly on your professionalism. In fact, using aggression to assert dominance is a strong indication of a lack of experience and deep knowledge in the subject. Those who are confident in their expertise typically rely on reasoning and facts rather than personal attacks.
The concern with goto is not that it allows completely unrestricted jumps like setjmp/longjmp, but rather that it disrupts structured programming principles by allowing arbitrary jumps within a function. While the scope of goto is indeed limited to the function where it is used, it still introduces non-linear control flow, making the code harder to read, maintain, and refactor.
Structured control flow constructs (if, while, for, etc.) inherently guide the programmer toward writing more predictable and maintainable code. goto can make this harder by allowing jumps that bypass normal scoping and sequencing, increasing the risk of unintended side effects.
Even in the cases where goto is used for error handling in deeply nested logic, it still leads to more harm than good. The fact that many coding guidelines, including those for large-scale projects and even the Linux kernel, discourage excessive use of goto reinforces this point.
If you have specific counterexamples where goto leads to clearer and safer code compared to structured alternatives, I'd be genuinely interested to discuss them. Let's keep the focus on technical merit rather than personal remarks.
-
I don't get it. Goto jumps to exactly where I put the label. It doesn't jump to "any" place within the function.
If you use it to jump to stupid targets, then... shame on you. You totally can use break and continue to do the same. You can wrap arbitrary pieces of code inside a loop and jump backwards (with continue) or forwards (with break) anywhere.
Seeing serious misuse of goto doesn't seem to be any more common than serious misuse of any other construct. Totally made-up problem.
In fact I would say that switch-case is a truly dangerous construct. Seen so many bugs with it. The fallthrough feature alone is much scarier than goto, which never does anything other than what is obvious from the code itself (jump to the explicit label). Still I won't call switch-case as evil and will keep using it. Switch-case is like a multi-goto on steroids, a total anti-pattern of structured programming.
-
I don't get it. Goto jumps to exactly where I put the label. It doesn't jump to "any" place within the function.
If you use it to jump to stupid targets, then... shame on you. You totally can use break and continue to do the same. You can wrap arbitrary pieces of code inside a loop and jump backwards (with continue) or forwards (with break) anywhere.
Seeing serious misuse of goto doesn't seem to be any more common than serious misuse of any other construct. Totally made-up problem.
In fact I would say that switch-case is a truly dangerous construct. Seen so many bugs with it. The fallthrough feature alone is much scarier than goto, which never does anything other than what is obvious from the code itself (jump to the explicit label). Still I won't call switch-case as evil and will keep using it. Switch-case is like a multi-goto on steroids, a total anti-pattern of structured programming.
The issue with goto isn’t that goto can jump to any place within a function - it’s that it allows arbitrary jumps that disrupt structured control flow.
Your argument assumes that goto always jumps exactly where the programmer intends, however, consider the original example from the topic starter - filled with bunch of labels and jumps across different parts of the functions. The goto statements do indeed jump to the exact labels placed by the author, exactly as intended. Yet, despite this, even the author of the code admitted that he don't fully understand how it works. This is precisely the problem - the goto statement may function correctly from syntax point of view, but the resulting logic becomes so tangled that even its creator struggles to follow it.
By contrast, switch-case does not suffer from this issue. It provides a structured way to branch execution, making the flow of logic transparent. Unlike goto, a switch statement explicitly maps inputs to execution paths in a way that is easy to follow. Of course, as with any construct, misuse is possible - for example, deeply nested switch statements can reduce readability. In such cases, refactoring into separate functions is a much better approach.
The key point is that structured programming constructs like if, while, and switch inherently guide developers toward more maintainable designs, while goto offers no such structure, making it far easier to create hard-to-follow code.
If you has studied graphs and understands what is tree structures, you can visualize a program's execution flow as a well-structured tree - where each branch represents a clear and predictable path of execution. This structured flow ensures maintainability, readability, and ease of analysis.
In contrast, excessive use of goto transforms this structured flow into a graph with arbitrary and chaotic connections between nodes. Instead of a predictable, hierarchical execution path, the program’s control flow becomes difficult to trace, making it significantly harder to analyze, debug, and modify. This lack of structure is precisely what leads to the well-known maintainability issues associated with goto.
The problem with goto isn’t just that it should be used rarely - it’s that it does not enforce constraints for structured control flow. This lack of constraint allows deviations from well-structured execution paths, making the code inherently fragile. Even a single goto, while seemingly harmless in isolation, introduces the possibility of uncontrolled jumps, breaking the guarantees of structured programming. As a result, any use of goto inherently degrades code quality, even if the overall structure remains visually intact and relatively easy to follow.
When working on a large project, you cannot manually verify how goto is used in every function. In a well-structured codebase, you can simply run a grep search for goto, and if no results are found, you can be confident that the control flow remains structured. However, if your search returns millions of lines containing goto, it becomes practically impossible to review every occurrence. The sheer volume makes it unfeasible to ensure that all uses of goto are safe and do not introduce unexpected or hard-to-trace execution paths.
By adding even a single goto to your code, where it may not immediately cause significant issues, you will eventually encounter a host of problems. For example, your version control system may reject your code due to the presence of goto, or your build system could fail because of it. While it’s possible to manually reconfigure the build process or request exceptions for your code with goto, this is a poor solution. In a professional environment, attempting to circumvent system constraints designed to maintain code quality in order to insert a single goto would not be accepted.
In reputable companies, every commit must adhere to established coding standards, and the build process is configured to immediately flag any potential errors or problematic code. As part of this, the code undergoes automatic analysis and inspection by parsers and code analysis tools during the build process. As a result, you won't even be able to commit code containing goto, and if you do manage to commit it, you will break the build and thereby attract the attention of the whole company.
This is exactly why even a single use of the goto statement, which doesn’t break code readability, still degrades the quality of your code and makes it shitty-code.
As you can see, this designation isn’t based on blind adherence to the idea that goto should never be used, on blind following guidelines, or for religious reasons, but rather stems from the practical challenges you will encounter when attempting to use even a single goto in your code. Even in the absence of strict rules, you will still face numerous potential issues associated with the use of goto.
-
In contrast, goto can jump anywhere
Every idiot can keep repeating this like a broken record, but it does not become true. Try it. Scope of jumping with goto is pretty limited. You would know that if you either read the standard, any tutorial worth of its salt, or, simply, just tried it yourself.
You are thinking about something like setjmp/longjmp. Oh, wait, no. You are not thinking.
Unfortunately it is common in this forum that personal responses are written with insults, due to differences in opinions.
While it is true that in technology there may be certain “truths” or opinions that can be “proven”, it is also true that we are people and we are entitled to say what we want. There is even the right to be wrong, without that justifying in any way personal attacks.
I do not agree completely with radiolistener. I don't like goto, but I understand that it can be used in structured programming without violating its fundamental principles (as Donald E. KNUTH argued many years ago in the article I posted).
In short, we are debating opinions and everyone after reading the arguments of others is very free to follow with his own.
For my part, I reiterate my support for radiolistener to have his opinion without being attacked for it.
-
Well, it's possible that radiolistener's first posts were a bit "sententious", but I think he ended up elaborating enough to make his point.
As I said earlier, I think there's nothing particularly elegant in using "goto", even when that's efficient, because it essentially lacks structure. We use it in C (sometimes), again for lack of better constructs. So "defending" its use in general doesn't make sense; it can be defended (even though not everyone will agree) when the language in question lacks better options.
Giving the example of nested loops, some could argue that the two below do not make any difference ("pseudo-code" here):
for (...)
{
for (...)
{
...
if (...)
goto GetOuttaHere;
...
}
}
GetOuttaHere:
....
and
OuterLoop: for (...)
{
InnerLoop: for (...)
{
...
if (...)
exit OuterLoop;
...
}
}
...
But there's a fundamental difference in terms of code structure. The second is more compact and much less error-prone. No amount of inserting code at the wrong place or moving a label could make it fail, and the intent is also easier to catch and analyze. It doesn't exist in C and C++, but it does in Ada. And I think I've heard it's coming for C.
Heck, some could even argue, taking this further, that the following is a perfectly valid and equivalent way of doing a for loop, and that for/while constructs are merely sugar-coating for this:
initialization;
MyForLoop:
if (condition)
{
body...
post statement;
goto MyForLoop;
}
Thus failing to see the merits of structuring code flow with easy-to-analyze constructs.
Of course, that's the extreme, although I can guarantee you that quite a few people won't see a single difference.
But again, most reasonable uses of goto in C are for breaking out of nested loops and avoiding duplicated code in error handling.
For the former, future revisions of C should solve that, as I mentioned. For the latter, it's doubtful.
And then, if you work in an environment with strict coding guidelines that forbid the use of 'goto', then problem solved: you don't have a choice. If you don't like it, change jobs.
-
One other thing. Just because I currently had a statement that shall not be named in my code, doesn't mean that I could have eventually come to understand C well enough to possibly, maybe, perhaps, eventually remove said highly offensive statement from the code???
Having people come in and stomp all over me with a pair of spiked boots certainly is conducive to learning, hm?????????????????
-
There is even the right to be wrong, without that justifying in any way personal attacks.
Absolutely not. Logical fallacies (https://en.wikipedia.org/wiki/Logical_fallacy) like arguments from authority are anti-science, anti-engineering, and need to be burned with fire and scorn in technical discussions. They are no better than using religion as a basis for technical and scientific decisions, and must be scorned, or we will fail.
Rules for primarily social interaction differ from those for technical discussions.
In a technical discussion, we do not pose opposing opinions. That is what social people do. It does not work for technology or science, because reality is not a social construct. Instead, we discuss the reasons behind those opinions. The opinions themselves are worthless; in fact, they have negative worth, unless the reasons behind those opinions are discussed, because only those reasons and experience can be compared. Opinions themselves are simply the current conclusion, and if stated in the "this is my opinion, take it what you will" manner, simply clutter a technical discussion without bringing anything that could be rationally and logically examined into it.
To simplify, opinions in isolation are worth shit, and deserve no respect. They are simply the conclusion, the wrapping paper around the thing itself.
I and others have described why specific uses of goto are warranted, in an effort to prove that a blanket statement like "using goto makes your code inferior and shitty" is simply provably incorrect; that it should be reserved for the very few cases where its use is better than any alternatives, but those few cases do exist. To generalise, no rule of thumb covers the entire domain, only a small subset of it.
Countering that by an argument from authority –– essentially, "I'm an expert, trust me bro", or "You think you know better than X?" –– is idiotic. It is what most humans do in social situations, yes, but in a technical discussion it is ridiculous and shows that the person is not interested in discussing the reasoning and logic behind their current understanding and opinions, and is instead engaging in social games like "saving face" and "looking for admiration" and "one-upmanship".
The only way to stop that that seems to work, is to insult the person who engages in that, in the hopes that they will reflect on it (some time in the future, perhaps weeks or months later), and adjust their output and interaction with other technical people. Ignoring such behaviour will only mislead others into believing there might be merit in that. All that is required for nontechnical bullshit to prevail is for rational logical people to ignore it.
(I'm sure that if I had better social skills, I could point that behaviour out in some sarcastic manner that is effective but is not personally insulting.)
Me saying "radiolistener is full of shit" is a colloquial expression intended exactly in that sense. I am not at all interested in online social dances and games; I am interested in problem solving, discussing understanding and experience (leading to various opinions), and helping others learn.
If you find this attitude or approach distasteful/unwanted/negative, take it up with Dave and the moderators. (I mean this at its face value: it is something you should try to discuss with them, if you have any kind of logical reasons for believing so. If you simply believe so or take that as an axiomatic truth, or expect technical people to respect even illogical and provably untrue opinions, do be ready to be laughed at.)
Please, do not try to passive-aggressively hint or indicate that it is somehow inferior/unwanted/negative in the hopes of changing others' behaviour: that is social, and this is a technical forum. Not everyone has the social sensibilities you do: what you think and believe is natural and professional conduct, is pure social nonsense to others, and vice versa. The only thing we can really rely on, as shown by the past few centuries, is rational and logical thought, the scientific method, and engineering (https://en.wikipedia.org/wiki/Engineering). As social animals, humans are easily misled using interaction tricks like logical fallacies and appealing to social hierarchies and popularity; those never lead to good technical or scientific outcomes. I know you believe in the wisdom of the herd and that popularity correlates with technical quality, but in science and engineering, those beliefs have been proven incorrect time and time again.
-
One other thing. Just because I currently had a statement that shall not be named in my code, doesn't mean that I could have eventually come to understand C well enough to possibly, maybe, perhaps, eventually remove said highly offensive statement from the code???
From what I can tell, you started well along constructing the intermediate form for the code, as I outlined in the latter section of my reply #72 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5868263/#msg5868263). Up to #14, I think the process started flowing, with the only real risk being you being satisfied with an un-maintainable intermediate version of the code. I particularly liked radiolistener's switch..case in #13 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5863129/#msg5863129).
It started to go awry in #15 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5863407/#msg5863407). Macros, just like gotos, have their uses. As an example, I often use the construct
// explanation of what CONFIG_VARIABLE controls
#ifndef CONFIG_VARIABLE
#define CONFIG_VARIABLE default-value
#endif
for my unit tests because it allows me to trivially rebuild the code with a different value, using -DCONFIG_VARIABLE=value compiler option (for GCC and Clang).
Especially in the intermediate representation of the code, it is very useful to replace magic numeric constants with macros.
In #22 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5865113/#msg5865113), you should have included the code itself between [CODE]..[/CODE] tags, because attachments like that are opened separately, so require extra effort to review the code. Inline code is better than any attachment, if you want many eyes on it.
In #25 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5865663/#msg5865663), tggzzz tried to get the thread back to rails by telling you (metertech58761) to concentrate on understanding and describing what the code does, instead of translating the code; something I repeated much later in #72.
In #29, metertech58761 tried to push back on the language authoritarianism, but to no avail. 😟 I tried to defuse the silly arguments from authority in #53 by describing counter-cases that are easy for anyone to verify for themselves. In #56, I was still amused by the silliness of (illogicality and authority-driven) repeated arguments, but by #58, I determined that radiolistener wasn't interested in logical rational discussion, only defending their self-view and opinions. I tried to describe the reasons why those claims were silly in #68 and #70, also trying to point out how many people misunderstand MISRA-C and DO178B to be coding standards, which they definitely are not: they are about the entire process, with the coding stuff just a subset chosen to make the process more efficient. The coding stuff alone, without the review-testing-verification cycles, will not bring any significant reliability/safety improvements, and therefore cannot be used as a guide to what kind of code is "safer" or "good" per se.
It is unfortunate that metertech58761's project thread got mired in language-authoritarianism (using Names and Status as proofs that certain practices are infallible and have no exceptions). It is very common in software threads, though.
The way I deal with this, is temporarily ignore the members I believe I cannot mutually beneficially interact with, using Profile > Summary, then Modify Profile > Buddies/Ignore List... > Edit Ignore List. I periodically empty that list, because I don't use it to "silence" others, I only use it to control what I react to. (For example, I do believe that if radiolistener had slightly more humility and much less authority-based/axiomatic assertions, they'd be a great asset for this forum and especially learners. I don't want them to be silent or to go away, I just want them to change how they argue. I also wish Picuino would realize that popularity and quality do not correlate in real life, but I don't seem to be able to sway their belief on that.)
I hope that metertech58761 and others reading this thread realize that even when their threads get mired like this, it does not mean the thread is lost: it just means they need to filter the content to focus on the technical aspects they grasp, and continue. (Asking the other discussers to stop will not work, and is often seen as an attempt of controlling what others discuss and thus hostile. I recommend against doing that.)
-
We are human and we are not even talking. We must not forget that with writing we lose many of the nuances of face-to-face speech and this tends to create a multitude of misunderstandings.
Nor should we forget that we are human. Full of illogical thoughts about popularity or authority, full of ideas based on logical fallacies and full of prejudices and biased ideas.
That a logical conversation can emerge from this breeding ground (and sometimes it does) is a true miracle.
-
Countering that by an argument from authority –– essentially, "I'm an expert, trust me bro", or "You think you know better than X?" –– is idiotic. It is what most humans do in social situations, yes, but in a technical discussion it is ridiculous and shows that the person is not interested in discussing the reasoning and logic behind their current understanding and opinions, and is instead engaging in social games like "saving face" and "looking for admiration" and "one-upmanship".
The only way to stop that that seems to work, is to insult the person who engages in that, in the hopes that they will reflect on it (some time in the future, perhaps weeks or months later), and adjust their output and interaction with other technical people. Ignoring such behaviour will only mislead others into believing there might be merit in that. All that is required for nontechnical bullshit to prevail is for rational logical people to ignore it.
It’s important to clarify something. I haven't relied on "arguments from authority." Instead, I’ve provided specific, practical examples of how using goto - even in seemingly harmless ways - can lead to serious maintenance, readability, and tooling issues in real-world projects. These are technical concerns grounded in experience, not appeals to status.
Ironically, by ignoring and dismissing these examples without addressing their substance and instead assuming your own position is unquestionably correct, you're doing exactly what you criticize: relying on your own perceived authority. By your logic, that would justify me responding with insults rather than reasoned arguments. And yet, I’ve chosen not to follow that path.
I believe that in a technical exchange, it’s far more productive and respectful - to engage with logic and real-world implications rather than try to assert dominance through hostility.
If the goal is to improve understanding and code quality, let’s focus on that, not on undermining each other personally.
(I'm sure that if I had better social skills, I could point that behaviour out in some sarcastic manner that is effective but is not personally insulting.)
Your problem isn’t a lack of social skills - it’s that the particular social skill you’ve developed happens to be confrontation. You're clearly experienced in using insults and provocation as tools in discussion. Instead of engaging in a technical dialogue about the use of goto, you focus on asserting your opinion as the only correct one (as the sole valid perspective) and as a result, you resort to insulting those who disagree, attempting to silence them and prevent others from hearing any viewpoint that challenges your own. That’s likely why it unsettles you when others disagree - it threatens the narrative you’re trying to impose as authoritative. You’re not aiming to exchange views, but to control how the issue is perceived.
Lacking the technical background to directly counter the points raised, you resort to personal attacks. This is a well-known manipulation tactic: diverting attention from substance to conflict when there’s no solid ground left to stand on. Unfortunately, this highlights where your real proficiency lies - not in engineering principles, but in derailing conversations through hostility. Perhaps that’s why you instinctively shift the discussion from reasoned argument to emotional escalation: because you recognize that in technical discourse, your position is weak, whereas in personal attacks and verbal aggression, you feel confident and experienced. It’s a deliberate move into a domain where you believe your strengths will give you the upper hand.
After all, by your own admission, insults appear to be your most reliable fallback when a technical argument doesn’t go your way. Isn't it?
With your strong inclination to dominate the conversation, dismiss dissenting voices, enforce a single narrative, and resort to aggression when challenged, you might have thrived in an environment built on authoritarian control and a dictatorship regime. However, in technical fields, such qualities tend to hinder collaboration and innovation rather than support them. Leadership in engineering demands openness to critique, respect for differing viewpoints, and the ability to engage constructively - even in the face of disagreement.
Unfortunately, this is common in technical fields when a young specialist, having gained a solid understanding of a particular topic, starts to view themselves as an authority. When someone expresses an opinion that challenges their views, it can deeply affect them, leading them to respond with aggression, insults, and other negative behaviors toward those who dared to disagree. They may believe that such a confrontational stance will help them maintain the position of being "always right," but in practice, life will eventually teach them that this tactic doesn't work in the long run.
-
Especially in the intermediate representation of the code, it is very useful to replace magic numeric constants with macros.
Using macros for magic numbers can lead to significant issues. Instead, it's better to use constants, enums, or inline functions, which provide better type safety, easier debugging, and improved maintainability. These alternatives make your code more robust and easier to manage in the long run.
Some reasons for that:
- Macros do not provide type safety. Since the preprocessor simply replaces the macro with its value before compilation, there's no way to check if the types are compatible at compile time. This can lead to unintended behavior and hard-to-find bugs.
- Macros don't provide the benefits of debugging and inspecting variables at runtime, unlike constants or enums. When debugging, you can't see the macro's value as a variable in the debugger. It's just a "text replacement" that could be anywhere in your code, making it difficult to track down problems related to its usage.
- Macros are globally visible and don't have the scoping rules that functions, constants, or enums do. This means that you might accidentally redefine or clash with existing macros in other parts of the code, leading to hard-to-diagnose issues.
- Macros don’t provide debugging or symbol information like constants or enums. If you replace a macro with an enum or a constant, debuggers and tools can give you more meaningful information when inspecting your program’s state.
- Macros don’t provide any semantic meaning beyond their value. When you use constants, enums, or inline functions, your code becomes more readable and maintainable because it’s clear what each value represents, and they can be easily refactored or modified if necessary.
-
There is even the right to be wrong, without that justifying in any way personal attacks.
Absolutely not. Logical fallacies (https://en.wikipedia.org/wiki/Logical_fallacy) like arguments from authority are anti-science, anti-engineering, and need to be burned with fire and scorn in technical discussions. They are no better than using religion as a basis for technical and scientific decisions, and must be scorned, or we will fail.
Rules for primarily social interaction differ from those for technical discussions.
In a technical discussion, we do not pose opposing opinions. That is what social people do. It does not work for technology or science, because reality is not a social construct. Instead, we discuss the reasons behind those opinions. The opinions themselves are worthless; in fact, they have negative worth, unless the reasons behind those opinions are discussed, because only those reasons and experience can be compared. Opinions themselves are simply the current conclusion, and if stated in the "this is my opinion, take it what you will" manner, simply clutter a technical discussion without bringing anything that could be rationally and logically examined into it.
To simplify, opinions in isolation are worth shit, and deserve no respect. They are simply the conclusion, the wrapping paper around the thing itself.
I and others have described why specific uses of goto are warranted, in an effort to prove that a blanket statement like "using goto makes your code inferior and shitty" is simply provably incorrect; that it should be reserved for the very few cases where its use is better than any alternatives, but those few cases do exist. To generalise, no rule of thumb covers the entire domain, only a small subset of it.
Countering that by an argument from authority –– essentially, "I'm an expert, trust me bro", or "You think you know better than X?" –– is idiotic. It is what most humans do in social situations, yes, but in a technical discussion it is ridiculous and shows that the person is not interested in discussing the reasoning and logic behind their current understanding and opinions, and is instead engaging in social games like "saving face" and "looking for admiration" and "one-upmanship".
The only way to stop that that seems to work, is to insult the person who engages in that, in the hopes that they will reflect on it (some time in the future, perhaps weeks or months later), and adjust their output and interaction with other technical people. Ignoring such behaviour will only mislead others into believing there might be merit in that. All that is required for nontechnical bullshit to prevail is for rational logical people to ignore it.
(I'm sure that if I had better social skills, I could point that behaviour out in some sarcastic manner that is effective but is not personally insulting.)
Me saying "radiolistener is full of shit" is a colloquial expression intended exactly in that sense. I am not at all interested in online social dances and games; I am interested in problem solving, discussing understanding and experience (leading to various opinions), and helping others learn.
If you find this attitude or approach distasteful/unwanted/negative, take it up with Dave and the moderators. (I mean this at its face value: it is something you should try to discuss with them, if you have any kind of logical reasons for believing so. If you simply believe so or take that as an axiomatic truth, or expect technical people to respect even illogical and provably untrue opinions, do be ready to be laughed at.)
Please, do not try to passive-aggressively hint or indicate that it is somehow inferior/unwanted/negative in the hopes of changing others' behaviour: that is social, and this is a technical forum. Not everyone has the social sensibilities you do: what you think and believe is natural and professional conduct, is pure social nonsense to others, and vice versa. The only thing we can really rely on, as shown by the past few centuries, is rational and logical thought, the scientific method, and engineering (https://en.wikipedia.org/wiki/Engineering). As social animals, humans are easily misled using interaction tricks like logical fallacies and appealing to social hierarchies and popularity; those never lead to good technical or scientific outcomes. I know you believe in the wisdom of the herd and that popularity correlates with technical quality, but in science and engineering, those beliefs have been proven incorrect time and time again.
I agree that logical fallacies and, in general, illogical and pseudo-religious arguments should not be part of a technical or scientific discussion. However, the reality is that they are used, and frequently.
From this fact what one would have to know is how to respond to that way of expressing oneself and this is where I differ from your way of expressing yourself in the previous message. And I am a bit surprised by your message because you do not usually behave in the way you defend.
The response to an illogical argument should, according to you, be aggressive to the point of insult, but it is not the right way to act in any internet forum, although it is also a fact that such behaviors exist.
It has seemed appropriate to me to take this discussion to another thread where it does not hinder the current thread and we can focus on dealing with this particular issue:
https://www.eevblog.com/forum/chat/aggressive-responses-considered-harmful/ (https://www.eevblog.com/forum/chat/aggressive-responses-considered-harmful/)
-
I agree that logical fallacies and, in general, illogical and pseudo-religious arguments should not be part of a technical or scientific discussion. However, the reality is that they are used, and frequently.
From this fact what one would have to know is how to respond to that way of expressing oneself and this is where I differ from your way of expressing yourself in the previous message. And I am a bit surprised by your message because you do not usually behave in the way you defend.
When logical fallacies or axiomatic beliefs are used instead of rational arguments, I do not recommend an immediately aggressive approach, true.
It is when they insist on it, and include social games as I mentioned, when I take out the matches and gasoline.
The reason for the aggressiveness in that case is twofold: one is the rejection of rational-logical discourse, which is an absolute requirement in a technical discussion. Any rejection of it will lead to failure. The other is social manipulation tactics, which I personally detest to the extreme. You see, I am personally very easy target for social manipulation, and am easily exploited because of that. I am becoming old enough to detect the signs, and have found that many people use social tactics to manipulate others without even noticing it themselves –– it is a skill they've developed unknowingly, and apply it because it works. I truly hate exploitation. In combination, this means that when such social tactics are applied, even if unwittingly/instinctively, my reaction will always be aggressive.
I have seen the damage such social tactics cause to technical projects, discussion, and understanding. I can list a number of technically very inferior and insecure software projects that are only funded and maintained because of social tactics. These projects are all well known for their horrible security history, filled with CVEs involving privilege escalation bugs going unnoticed and possibly exploited in the wild for years.
I reject any suggestion that avoids confrontation when that occurs.
The response to an illogical argument should, according to you, be aggressive to the point of insult, but it is not the right way to act in any internet forum, although it is also a fact that such behaviors exist.
And exactly why do you claim it is not the right way to act?
My reasoning is shown above: because showing aggressive opposition to the behavioural pattern above is required to stop it harming the discussion/project/understanding. Unless you can show a response pattern that is at least as effective, I say your opinion on this is irrelevant, because your suggestion does not work in practice.
(Note that while the optimum result would be to change that persons communications patterns, that rarely happens immediately; it takes repeated pushback for this to have that effect. What it does do, however, is make it easier for others, especially "lurkers", to see how the discussion is being manipulated by social tactics, and apply their own logic and do their own research wrt. the claims shown, to avoid being misled.)
To repeat: all it takes for social manipulation and illogic to work and lead to technically inferior results, is for technical people to be silent about it.
In this case, it is utterly clear that while radiolisteners first response was excellent and useful, their followup posts, if taken at face value, would lead to technically inferior results and unnecessarily limited process. (Avoiding the use of goto in the intermediate representation makes the work much, much harder, because instead of changing the representation as a first step, using goto for assembly branches and jumps, one has to directly write the corresponding "non-goto" C construct at once; this easily leads to bugs, because the intermediate representation is no longer visible, and thus cannot be checked.)
[aggressive responses considered harmful -thread]
That is set of axiomatic beliefs that leaves no room for discussion. It is written in the technical style –– I see you used the old social trick of adapting the style I used in why writing style and grammar matters in posts (https://www.eevblog.com/forum/beginners/why-writing-style-and-grammar-matters-in-posts/), but replacing the reasoning portions with axiomatic statements in a technical-looking style that leaves no room for argument or dissent.
Well done. It is a perfect example of a post that will be appreciated by those who agree with your beliefs, but leaves no room for rational discussions on your axiomatic statements, and therefore is unlikely to garner any opposing responses, thus reinforcing your belief in your axioms. That post is a perfect example of the social games I often mention, even though I truly believe you did this in good faith.
Consider how anyone having a solid logical reason why your axiomatic "rules" are incorrect would/could respond to you? The way you wrote your post leaves no room for such discussion. Even the title is the conclusion expected from such discussions. (That alone is a social trick, exploiting the agreeableness (https://en.wikipedia.org/wiki/Agreeableness) human personality trait (and specifically its compliance (https://en.wikipedia.org/wiki/Compliance_(psychology)) sub-trait), starting by discreetly explaining what is expected of others.)
I'd be willing to bet 2€ that you will only get responses from members that simply agree with you. If that happened to me, I'd be alarmed and disappointed in my own writing style. The best case to me is always a discussion, even an argument, or an expansion or delving deeper into the details and exceptions to the initial statement. If my post leaves no room for that, it is simply a statement and not a discussion; something far less useful. (I'm particularly unhappy with how I started this (https://www.eevblog.com/forum/programming/constructing-short-c-strings-in-limited-or-constrained-situations/msg3599104/) and this (https://www.eevblog.com/forum/programming/mind-over-bugs-c-pointer-edition/msg3597314/) thread. If I had posed those as questions –– even if I had one possible answer myself that I wanted to show to others and discuss ––, the discussion would likely have included other, perhaps even better approaches, with mine just as an example. As it is, they are not very useful threads, and didn't reach details a questioning approach could have; thus wasteful/disappointing.)
-
Now, I don't see any reason to use goto at all. And it's important to note - not because it's considered bad practice, not for religious reasons, and not because any particular group of people or company believes it's wrong, but simply because I don't see any practical situations where goto would be beneficial, especially since I know more effective solutions that can be implemented without it.
That's an ultra-common topic as it seems and comes back on a regular basis.
You'll find the usual, "goto's are bad" and "those who say goto's are bad are just ignorant wankers with no practical experience".
I'm not sure either are very useful, but hey. There's little as polarizing as programming topics. And politics.
I often like to start with the obvious, that is the rationale of the original paper it originates from, which was just trying to convince people of the benefits of structured programming, which was absolutely not a given at the time. These days, nobody reaosnable would even question "structured programming", so that context is almost entirely lost.
The second point is that, apart from assembly with "branches", most uses of "goto" are in C and C++ when it's a convenient and efficient way of breaking out of some nested loops, or for error handling, where you have a function with many possible paths of error and a single point to go to to handle the error before returning. That's mostly for lack of better constructs, not at all because goto is cute, even less so an elegant way of dealing with program flow. But it works given the limitations of those languages.
Some other languages have proper ways of dealing with the same, like named loops (which are coming with C23 if I'm not mistaken?) and 'defer' constructs. I don't think anyone sane would prefer using "goto" rather than those two alternatives, but of course, YMMV.
Now even in C, there are ways you can often avoid goto for typical error handling, which I tend to prefer these days, although that's relatively recent. Instead of using goto, I'll wrap code that can produce errors in "do {...} while (false)" constructs, which I just 'break' out of after setting an error value, in case of error. The error value is tested after this "loop", and that often looks cleaner. Additional benefit is you can ultra easily turn this construct into "retry" construct by changing changing the do...while to a for with a certain number of iterations.
For breaking out of nested loops, unfortunately, I have no magic trick (until we get named loops). One common way of avoiding 'goto' in this case is to use flags, but that often looks clunky and is possibly less efficient, depending on the order in which you place the flag test in the loop conditions. Occasionally, it can make things more readable, as it shows the complete condition of a loop in only one place, but most often, it's just clunky.
I agree.
In C you can consider the use of 'continue' as a goto as well. IMHO what should drive the use of goto / continue is whether it leads to code which is easier to understand (*). Code which is easier to understand is less prone to bugs (including ones added later on through code modifications) and cheaper to maintain. Sometimes structuring code to make it simple requires a bit more work to write. Just like writing a short, to the point letter takes more time than three pages of rambling which doesn't get the message across.
* So far my practical use of goto in C is limited to jumping to do a single cleanup in case an init has failed. The Linux kernel is riddled with this programing pattern. Including situations where it is less appropriate with several exit points which makes code less easy to follow / maintain (as Radiolistener already noted).
-
I'd be willing to bet 2€ that you will only get responses from members that simply agree with you.
So true that I had to intervene and add some disagreement :box:
-
[aggressive responses considered harmful -thread]
That is set of axiomatic beliefs that leaves no room for discussion. It is written in the technical style –– I see you used the old social trick of adapting the style I used in why writing style and grammar matters in posts (https://www.eevblog.com/forum/beginners/why-writing-style-and-grammar-matters-in-posts/), but replacing the reasoning portions with axiomatic statements in a technical-looking style that leaves no room for argument or dissent.
Well done. It is a perfect example of a post that will be appreciated by those who agree with your beliefs, but leaves no room for rational discussions on your axiomatic statements, and therefore is unlikely to garner any opposing responses, thus reinforcing your belief in your axioms. That post is a perfect example of the social games I often mention, even though I truly believe you did this in good faith.
Consider how anyone having a solid logical reason why your axiomatic "rules" are incorrect would/could respond to you? The way you wrote your post leaves no room for such discussion. Even the title is the conclusion expected from such discussions. (That alone is a social trick, exploiting the agreeableness (https://en.wikipedia.org/wiki/Agreeableness) human personality trait (and specifically its compliance (https://en.wikipedia.org/wiki/Compliance_(psychology)) sub-trait), starting by discreetly explaining what is expected of others.)
I'd be willing to bet 2€ that you will only get responses from members that simply agree with you. If that happened to me, I'd be alarmed and disappointed in my own writing style. The best case to me is always a discussion, even an argument, or an expansion or delving deeper into the details and exceptions to the initial statement. If my post leaves no room for that, it is simply a statement and not a discussion; something far less useful. (I'm particularly unhappy with how I started this (https://www.eevblog.com/forum/programming/constructing-short-c-strings-in-limited-or-constrained-situations/msg3599104/) and this (https://www.eevblog.com/forum/programming/mind-over-bugs-c-pointer-edition/msg3597314/) thread. If I had posed those as questions –– even if I had one possible answer myself that I wanted to show to others and discuss ––, the discussion would likely have included other, perhaps even better approaches, with mine just as an example. As it is, they are not very useful threads, and didn't reach details a questioning approach could have; thus wasteful/disappointing.)
Fortunately the initial post is generating debate. It is true that I started it with a series of affirmations that I believe are not open to discussion, but it was not my intention to make a closed discourse and I was relatively convinced that there would be contrary opinions. I only hope that the debate does not degenerate into useless discussion.
-
I'd be willing to bet 2€ that you will only get responses from members that simply agree with you.
Fortunately the initial post is generating debate.
:-//
I never, ever claim I'm always right. (That's also why my current opinions are not worth anything, just like everyone elses, only the reasoning, logic, and experiences that lead to those opinions matters.) And when I'm wrong, I do clearly admit it; just look at my posting history.
While I don't think the thread responses have much to do with your first post, and are more generally about why certain behavioural patterns occur in online discussions (and what exactly constitutes trolling), I do agree I would have lost that bet. If there is an IBAN account or purpose you want me to put that 2€ towards, just say so or PM me the details.
-
Here's the rewrite after some structural work to get the three two-way suites into one.
I can't see how to minimize the goto statements - most are attached to conditionals, the only 'hard' goto statements are returning to the main loop or to the error handler.
// Two-way unit test suite (LMT-2 / MCT-2xx / DCT-501)
// Variables guiding this suite:
// testSet: 0 (test), 1 (install), 2 (read + test), 3 (DCT read), or 8 (short read)
// uutType: 2 = LMT-2 / MCT, 4 = DCT
suite2:
if (testSet == 1) { test15(); } // download address to UUT
suite2_01:
test20(); // Read / verify UUT address
if (testSet == 0)
{
test20a(); // display UUT address
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_01; }
}
if (testSet == 3) { goto suite2_12; } // DCT tests
// Test 25: Get hardware ID
suite2_02:
dispBlank(); // Clear 4x20 LCD
testNum(25); // LCD top row: '25: Get Hardware ID '
msgBtemplate(); // Default template for 2-way messages
msgDataQry(); // Request data from UUT
if (testSet == 8)
{ if (uutType != 2) { goto suite2_04; } }
// Error-check data based on UUT response
// Error 5: Other Data error
if ((msgRec[1] & 0x1F) != (addrM & 0x1F)) { goto error5; }
if (msgRec[2] != addrL) { goto error5; }
// Address check passed, so save UUT data
uutFWbyte = msgRec[3]; // Firmware number
uutFWspec = msgRec[4]; // Firmware revision
optbyte = msgRec[5]; // Installed option (i.e., latching relay)
// Determine UUT group based on firmware
// We have units with S00036 and S00095 on hand
suite2_03:
// S00001 - suspected LMT-1
// S00036 - LMT-2
if (uutFWbyte == 1 || uutFWbyte == 36) { uutGroup = 2; goto suite2_05; }
// S00074 - MCT-212, MCT-213, MCT-22x
// S00093 - MCT-240, MCT-242
if (uutFWbyte == 74 || uutFWbyte == 93) { uutGroup = 4; goto suite2_05; }
// S00088 - MCT-210
// S00095 - MCT-210, MCT-213
if (uutFWbyte == 88 || uutFWbyte == 95) { uutGroup = 6; goto suite2_05; }
// S00008 - suspected DCT
// S00033 - DCT-501
if (uutFWbyte == 8 || uutFWbyte == 33) { goto suite2_21; }
// We have now gone through all the known FW specs - so we have a problem
// Error 7: Unknown firmware
suite2_04:
readout = 7; // LCD row 1 RH: 'Error 7', row 2: 'Unknown Firmware!'
getFWRev(); // read again, display data on row 3
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_02; }
uutGroup = 4;
if (testSet == 8) { goto suite2_06; }
else { goto suite2_08; }
// Now let's get the DCT check from the tree out of the way
suite2_21:
if (uutType == 4) { goto suite2_08; }
else { goto suite2_04; }
// If we did not request the short read script, skip ahead!
suite2_05:
if (testSet != 8) { goto suite2_07; }
// Begin short read (tests 45, 47, 48)
suite2_06:
test_45(); // Get and display reading (kilowatthours)
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_03; }
// Unless we are testing LMT-2s, we are finished - return to main menu
if (uutGroup != 2) { goto loopMain; }
test_47(); // Get and display reading (pulse initiator 2)
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_03; }
test_48(); // Get and display reading (pulse initiator 3)
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_03; }
// Finished with short read - return to main menu
goto loopMain;
// Now we continue from the intermission
suite2_07:
if (uutType != 2) { goto suite2_04; }
// Validate the presence of latched relay and FCT Control Number
// optByte bit 0 leads the way
// Error6: Incorrect FCT Control #
if (optByte && 1 == 0)
{ if (fctCtlNum != 0) { goto error6; } } // bit 0 = 0, so fctCtlNum MUST be 0
else
{ if (fctCtlNum == 0) { goto error6; } } // bit 0 = 1, so fctCtlNum CANNOT be 0
suite2_08:
ledStat = 7; // LCD display (row TBD): 'ID successful'
displayRefresh();
wait(1000); // Wait 1000mS = 1 second
// Now we find our way outta here into the actual test suite
if (testSet != 1) { goto suite2_09; }
if (uutType == 4) { goto suite2_11; }
if (uutGroup == 2) { goto suite2_11; }
else { goto suite2_10; }
// Main suite
suite2_09:
test_26(); // Get UUT test mode status
if (lmtTestMd != 0) { if (uutType == 4) { goto suite2_14; } }
test_27(); // Enable test mode in UUT
suite2_10:
test_28(); // MCT related - perhaps for entry of multiplier, Mp, or Kh?
if (uutGroup == 6) { test_29(); } // MCT related - may be for multiplier, Mp, or Kh?
suite2_11:
test_30(); // Reset error flags, inhibit time sync, reset battery time
suite2_12:
if (uutGroup == 0) { goto suite2_13; } // possible skip for when CCU is being read
if (uutGroup != 2) { goto suite2_18; }
suite2_13:
test32(); // function TBD
// exit if DCT group was selected
if (testSet == 3)
{
ledStat = 7; // LCD display (row TBD): 'Test group complete '
displayRefresh();
keyMask = 0b01001000;
goto loopMain;
}
suite2_14:
if (uutType == 2) { goto suite2_18; }
// DCT test group
suite2_15:
test_61(); // Read Analog 1 - 2nd row, left
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_15; }
test_62(); // Read Analog 2 - 2nd row, right
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_15; }
test_63(); // Read Analog 3 - 3rd row, left
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_15; }
test_64(); // Read Analog 4 - 3rd row, right
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_15; }
// optByte bit 1 seems to be flag for relay type in DCT - timed or latched
if (optByte && 2 == 0)
{
suite2_16:
test_70(); // Download bytes $3A - $3D and TOU delay status flags from DCT
test_71(); // sends long-form message to UUT
test_72(); // Strobe DCT relays
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_16; }
test_73(); // Write dctData1 - dctData4 back to $3A - $3D in DCT
}
else
{
test_75(); // fetch flag from DCT, save in dctData1
suite2_17:
test_76(); // Relay tests
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_17; }
}
if (testSet != 1) { test_78(); } // turn off test mode in DCT
test_80(); display toggle switch status
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_15; }
// LCD display (row TBD): 'Test group complete '
keyMask = 0b01001000;
goto loopMain;
suite2_18:
test_35b(); // Exercise timed relays
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_18; }
suite2_19:
test_40b(); // Exercise latched relay
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_19; }
suite2_20:
test_46(); // Display Pulse initiator count
// Display 'Repeat / Next?' on LCD row 4
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto suite2_20; }
if (testSet != 1) { test_50(); } // Turn off test mode in UUT
// LCD display (row TBD): 'Test group complete '
keyMask = 0b01001000;
goto loopMain;
// End of 2-way tests
I took the liberty of expanding the code inline, as it makes it much easier to read the code.
Have you progressed any further on this yet?
The pattern of
label:
do stuff
while((ch = getKey()) != KEY_NEXT)
{ if (ch == KEY_REPEAT) goto label; }
are easiest to implement as a separate function, and telling the C compiler that these functions cannot be called from external code and the compiler is free to inline them. One possibility is, for example,
static void do_label(void) {
int ch;
while (1) {
do stuff;
while (1) {
ch = getKey();
if (ch == KEY_NEXT)
return;
if (ch == KEY_REPEAT)
break;
}
}
}
although others exist. (Your main code would simply call do_label() for each test suite. Do think of better, more descriptive names, though.)
I'm having a bit of difficulty concentrating on this, so I'm hoping other members (radiolistener and Picuino included) will suggest even better (easier to read and maintain) patterns; my point is that there is a clear path forwards, and something like this would be my next step. (I admit, I personally would need to put this particular code aside for a couple of days due to the related discussions affecting me negatively, before I'd be able to get the results I'd be happy with.)
I suspect that for me, the end result would be a state machine, so an alternative approach would be to construct the state diagram from the code as it is now, and reimplement that. This one has enough parts that instead of drawing it by hand in Dia or Inkscape or other tools, I'd use Graphviz (https://graphviz.org/) for this, defining the structure in DOT language. If you want an example of that, install Graphviz for your system (it's free and available for all OSes), and I can show how I'd describe at least the first few suites in DOT, and what the ensuing state graph I'd do would look like.
-
I'd be willing to bet 2€ that you will only get responses from members that simply agree with you.
Fortunately the initial post is generating debate.
:-//
I never, ever claim I'm always right. (That's also why my current opinions are not worth anything, just like everyone elses, only the reasoning, logic, and experiences that lead to those opinions matters.) And when I'm wrong, I do clearly admit it; just look at my posting history.
While I don't think the thread responses have much to do with your first post, and are more generally about why certain behavioural patterns occur in online discussions (and what exactly constitutes trolling), I do agree I would have lost that bet. If there is an IBAN account or purpose you want me to put that 2€ towards, just say so or PM me the details.
Since you acknowledge being indebted to me, I would like to collect it from you in a simpler way.
I usually greatly appreciate your responses and the temperance with which you express them.
Considering that in this matter I consider you not to have a strong bias, I will be paid if you contribute with your opinion to the thread I opened, when you consider it appropriate (today or in a year).
-
Especially in the intermediate representation of the code, it is very useful to replace magic numeric constants with macros.
- Macros don't provide the benefits of debugging and inspecting variables at runtime, unlike constants or enums. When debugging, you can't see the macro's value as a variable in the debugger. It's just a "text replacement" that could be anywhere in your code, making it difficult to track down problems related to its usage.
Eclipse CDT was able to resolve macros on-the-fly while debugging. At least it was able to do this five years ago.
BTW. how does one resolve compile-time computations without macros in case when pre-C23 compilers are used?
And what about functions which on some platforms execute an action, and on other platforms they are effectively a no-op and should not get executed?
Because it is likely that one might not want to push/pop registers because of a no-op.
- Macros are globally visible and don't have the scoping rules that functions, constants, or enums do. This means that you might accidentally redefine or clash with existing macros in other parts of the code, leading to hard-to-diagnose issues
Can you please clarify this one and define what does "globally visible" mean?
-
Since you acknowledge being indebted to me
Don't be ridiculous. I acknowledged I would have lost that bet, out of honesty. That's all.
Never, ever mistake humility for weakness or honesty for capitulation. Some of us have a strict mental backbone, and value humility and honesty as mutually beneficial human interaction strategies –– when reciprocated. When they are exploited, we retaliate.
In particular, I wrote reply #110 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5873958/#msg5873958) to OP and others who are uninterested in the religious dogma/programming axioms posed by some and the tone policing attempts, and would rather just discuss useful technical stuff instead.
I usually greatly appreciate your responses and the temperance with which you express them.
I strive for mutually beneficial discussions based on logic and rational thought. When axiomatic beliefs and logical fallacies are substituted for logic, I escalate. When social gaming/tricks –– even if inadvertent ––, I escalate. The three last steps in that ladder are sarcasm/humor/poking fun, aggression, and personal insults. This is not a personal "preference"; it is simply what I've found works best. Do recall that I do not have the innate social skills most people have; I've had to empirically learn those the same way others learn math, science, or engineering. Lots of observation and analysis.
(I'm not emotionless, though. Sometimes my emotions get the better of me, like they do for most other people. None of that here, though: all I've felt is frustration with seemingly reasonable but functionally incorrect advice. It is very much what I feel when the output of LLMs is taken as intelligence, or the TIOBE popularity index is considered as an useful gauge of programming languages due to "wisdom of the herd".)
I would suggest that instead of telling others to stop using such tools, you try to find at least equally functional tools of discourse, and then start a thread showing others how and why those tools work and are superior.
(Think about it: wasn't my grammar thread exactly that? Now, compare to your own initial intent for your own thread.)
Do note that in online discussions such as these, the discussers are surrounded by a huge crowd just listening in. My goal here is to help everyone not be misled by incorrect/dysfunctional advice –– by others, or even by myself –– and to notice the most useful advice. You can see this in my posting history, if you care to check. I will not let any feelings or social niceties get in the way of that in technical discussions, because good advice is more important than appearance or feelings.
As it is, your new thread sounds to me like "When you respond to my unfounded beliefs stated as truths with aggression and insults, I feel bad inside. Please stop! Just because I'm wrong does not give you the right to point it out to others. I have the right to mislead others, if I want to!" – just clad in technical-seeming form. It's already spread from the definition of "trolling" into specific details in childhood psychology by people with no knowledge of psychology. Utterly useless bickering, I believe.
-
Especially in the intermediate representation of the code, it is very useful to replace magic numeric constants with macros.
Using macros for magic numbers can lead to significant issues. Instead, it's better to use constants, enums, or inline functions, which provide better type safety, easier debugging, and improved maintainability. These alternatives make your code more robust and easier to manage in the long run.
Some reasons for that:
- Macros do not provide type safety. Since the preprocessor simply replaces the macro with its value before compilation, there's no way to check if the types are compatible at compile time. This can lead to unintended behavior and hard-to-find bugs.
- Macros don't provide the benefits of debugging and inspecting variables at runtime, unlike constants or enums. When debugging, you can't see the macro's value as a variable in the debugger. It's just a "text replacement" that could be anywhere in your code, making it difficult to track down problems related to its usage.
- Macros are globally visible and don't have the scoping rules that functions, constants, or enums do. This means that you might accidentally redefine or clash with existing macros in other parts of the code, leading to hard-to-diagnose issues.
- Macros don’t provide debugging or symbol information like constants or enums. If you replace a macro with an enum or a constant, debuggers and tools can give you more meaningful information when inspecting your program’s state.
- Macros don’t provide any semantic meaning beyond their value. When you use constants, enums, or inline functions, your code becomes more readable and maintainable because it’s clear what each value represents, and they can be easily refactored or modified if necessary.
While there can be many pitfalls with those macros from the C preprocessor (used both by C and C++), I am personally against cutting off their use altogether (as you seem to suggest), because there's no serious alternative for many things, at least in particular with C. When using C++, there are a lot more tools available to avoid them (but C++ brings its own set of issues... which is another topic entirely/)
Of course, again, as I mentioned for 'goto', if you work in an environment where "macros" are forbidden, the story ends there. Exposing the fact they are forbidden and the underlying rationale is interesting, but "debating" it is pointless, when you have no choice.
With that said, I'll comment some of your points above:
- Type safety: true, but in C, enums do not provide any type safety either past being an 'int'. They even end up in the global namespace. The only real benefit is to group some definitions logically in enums for the developer and reader's benefit, but that's pretty much it. At least you can't use a string literal as an enum value, at least if your compiler is not too dumb or permissive. Yeah, not that pretty either. The situation is a bit better in C++ for sure, although simple enums are still compatible with int's in a number of contexts, making them barely any better than in C, except for the namespacing. You need to use "enum class" in C++ to get something with more strict typing.
- Using functions rather than macros when appropriate is generally a good idea. Qualifying them "inline" allows you to define such functions in header files and reuse them everywhere while avoiding multiple definitions. You can alternatively qualify them just "static", but the "inline" qualifier conveys the intent better IMO. Just a detail. Any decent optimizing compiler will just emit code that's inlined and usually as efficient as a macro.
- Decent debuggers know about macros - at least for defining "constants" (ie. named literals). GDB certainly does. Of course, function-like macros are harder to deal with when debugging though, but that's expected.
- Macros provide semantic as long as you pick decent names for them, following some general code style and sticking to it, instead of cryptic ones.
- As "ugly" as they may look, past the cases above, macros allow things that are otherwise impossible to do without - when you want some genericity. Again, in C, which was the center of this thread. In C++, you have templates, with their own possible downsides, but still much more elegant for writing generic code.
- Bonus pitfall: in C, "const" is definitely not a "constant" in the sense you meant - it's a read-only variable. There are a few ways in which it is quite different from a macro just substituting a literal. For instance, you normally can't use a const variable as a size for a global array. As for local arrays, you can, but you'll make them VLAs doing so, whether you like it or not. Yes yes, even if it's a "const".
All this, along with goto, and I know I'm just repeating myself, but this is very specific to C and languages with similar limitations. With C++, you have constexpr and templates. With Ada, you have more features at your disposal to make all of the above completely moot than you could even think of.
Just a few points.
-
#include <stdio.h>
int i = 3;
int main()
{
int i = 4;
printf("%d\n", i);
return 0;
}
$ gcc t.c -Wall -Werror && ./a.out
4
#include <stdio.h>
#define i 3
int main()
{
#define i 4
printf("%d\n", i);
return 0;
}
$ gcc t.c -Wall -Werror && ./a.out
t.c: In function ‘main’:
t.c:7: error: "i" redefined [-Werror]
7 | #define i 4
|
t.c:3: note: this is the location of the previous definition
3 | #define i 3
|
cc1: all warnings being treated as errors
Conclusion: macros are safer than variables. Variables considered harmful.
-
Decent debuggers know about macros - at least for defining "constants" (ie. named literals). GDB certainly does.
Yup, I can confirm this about GDB.
-
Of course, again, as I mentioned for 'goto', if you work in an environment where "macros" are forbidden, the story ends there. Exposing the fact they are forbidden and the underlying rationale is interesting, but "debating" it is pointless, when you have no choice.
Usually, macros are not entirely forbidden in most environments, but it's important to use them with caution and avoid overusing them. While they can be powerful, they also come with risks like lack of type safety and harder debugging. Unlike goto, which is generally banned outright in most coding standards, macros are typically allowed but expected to be used responsibly and sparingly.
-
cool story, people. Came here looking for guidance, and I got a holy war in return. Not sure where I go from here.
Edit: toned it down a bit.
-
cool story, people. Came here looking for guidance, and I got a holy war in return. Not sure where I go from here.
You read and understand the various points that have been made. Then apply those which seem applicable to your case. Preferably without shouting.
If you were expecting to be handed the answer on a plate, then stackexchange might be a better venue. It is good for problems with a simple solution. (But your problem isn't simple.)
-
Not sure where I go from here.
I can recommend Stack Overflow for you. It's a Q&A site, which EEVBlog forum is not. They have strong moderation and focus on just answering the question, and any tangential content, even if on-topic for the site but not exact answer for the question, is downvoted and automatically hidden, or moderated away.
You can also try LLM's like ChatGPT if they are helpful.
-
tggzzz: The thread took a turn deep into "this pedantic semantics argument helps me how?" territory. Lost interest once the post count went well beyond 50 with minimal involvement on my part.
Siwatsja: Noted. When and if, especially if, I want to resume this, I'll look into setting up an account over there. Thank you.
-
The thread took a turn deep into "this pedantic semantics argument helps me how?" territory.
This happens to every thread where radiolistener appears, nearly every time. Don't take it too seriously; learning how to skip messages is a valuable skill on discussion forums. Just keep discussing your stuff with those who give useful responses to you. You can thus help keep the discussion on your desired track. If you panic and run away, or start shouting others to shut up, then it's game over.
-
Lost interest once the post count went well beyond 50 with minimal involvement on my part.
Like Siwastaja wrote, just skip the noise, perhaps even temporarily ignore some members (Profile > Summary, Modify Profile > Buddies/Ignore List ... > Edit Ignore List). Online, you need to be selective and tenacious to get good results.
To add to what I suggested in #110, you could also consider replacing the interaction pauses with
ch = interactive_wait("Repeat / Next?", keymask);
where the function does the LCD display and waits until one of the buttons specified in the keymask set is pressed, then returns that value. (If you only have the two buttons, the mask is not needed.)
You'll see that this simplifies many of the loops where the current form still uses goto; you can also combine this with the sub-function approach I showed in #110.
This is also a perfect example of when simulating the user interface can help a lot. Seeing as you use C on a very limited microcontroller, I would suggest a very simple command-line/terminal program, using either termios (Linux/Unix/BSD/mac/WSL2) or Curses, with a very simple single-file program skeleton providing the LCD display functions, waiting for the repeat/next keypress (or other keys), and a debug logging so that the individual tests (like test15();) are mocked up by functions that just visibly log something like "Test 15 now running".
That way, you can easily test different refactorings of the test suite sequence and user interface. Like I mentioned in #110, I suspect that a simple state machine describing the menu structure, each node naming a function to call, text shown on the LCD, and pointers to structures for each key when pressed, would probably yield more easily maintained C code. (Plus, if you run from Flash, those structures are also in Flash and not in RAM.)
typedef struct suite suite;
struct suite {
void (*tests)(void);
const char *display;
const struct suite *repeat;
const struct suite *next;
};
The nice side of this is that it is easy to then document the navigation hierarchy (at build time) using a simple program that emits Graphviz DOT language graph of the tests, with each node having the display text, and labeled arrows pointing to the nodes advanced to when pressing next or repeat.
-
:-DD No, that's just your misunderstanding, confusing bad uses of a tool for the tool itself, and therefore labeling the tool bad. Your viewpoint is utterly simplistic, and therefore ridiculous.
If you knew anything about maintainable code or avoiding bugs, you'd know that the Linux kernel has much lower bug density compared to any enterprise code. Your own company, even if producing code used for critical life-sustaining equipment, almost certainly has a higher bug density; the only way you're not mired in lawsuits is a strict review and testing cycle (or clients that just don't notice or know any better). Labeling certain tools as "shitty" and "poor quality" is just their way of trying to wrangle lower-quality developers like yourself into producing something that can be shipped after sufficiently rigorous testing and review.
Having worked on medical device projects that undergo regular testing and audits, I can confidently say that, compared to the level of rigor I have observed in such environments, the Linux kernel is a mess of poorly structured code with numerous bugs. However, this is not to say that Linux is inherently bad or mismanaged - I fully recognize that it is a free, community-driven project that lacks the level of funding necessary to enforce strict development practices. In fact, considering these constraints, I’d say it is holding up remarkably well, and I genuinely appreciate its development. That said, comparing it to large-scale commercial projects with significantly stricter methodologies and regulatory requirements would simply be incorrect.
I agree here. Having 20+ years of experience fixing & modifying the Linux kernel myself I can say the Linux kernel is a prime example of extremely poorly written C code. The code is very frugal and I have seen it break in places leading to hard to trace bugs. Most recently due to changes to the way GPIO pins are enumerated. Not all drivers got updated but due to the lack of using a specific type the compiler doesn't even throw a warning and good lucking using code analysis tools. As a result some drivers get fed with illegal values resulting in all kinds of odd behaviour. This cost me a day I could have spend on doing something useful instead of figuring out somebody has messed up the GPIO handling.
-
I agree here. Having 20+ years of experience fixing & modifying the Linux kernel myself I can say the Linux kernel is a prime example of extremely poorly written C code.
I don't really disagree, but "prime example" "extremely poor" sound like exaggeration. I mean, it has quite decent track record of working, and the track record of it being maintained for over 30 years and scaling to things never originally imagined, while almost every other alternative failed to do that, means it can't be totally hopeless.
I can accept saying it's not ideal, or that it could be better, but I'm sure there will be much better "prime examples" of "extremely poorly written C code". For starters, maybe pick something that is so buggy that it does not work, or that completely breaks with every update, or requires massive amounts of man-hours and money to maintain? Linux kernel is not issue-free, but it also doesn't tick any of those boxes. It almost always Just Works and most issues on linux systems are on userland side. Sometimes someone steps on a footgun that could have been avoided by better coding practices but clearly this haven't caused enough pain to drive any kind of large-scale shift into better coding style. In other words, clearly it's good enough; I'm sure it's horrible for purists and idealists.
And academics especially hate the linux kernel, since it reminds them every day that such "amateurish" coding style "with goto and all" can be so succesful and work so well, when their elegantly designed software science ideas fail. Heck, I remember from Uni that even the existence of C language was too much to some. But practice always wins over theory.
-
Basically your argument is 'it works, so it can't be bad'. But that is the wrong way to look at it. Linux kernel coding style is like Evel Knievel coding. Only very highly 'skilled' people can write and maintain code like that. Judging by how Linus tends to react to (cancel) people wanting to simplify things you can argue he only likes coding acrobats / stunt people to work on the kernel. The problem is that not everyone is a coding acrobat and stunts tend to go wrong every now and then. Evel Knievel broke many bones in his carreer as a stunt man...
If you lead a team of programmers to work on a commercial project, you will want to lay down some coding style ground rules (like MISRA for example) and probably some additional ones as well to make sure the code has a certain level of quality (as in maintainability and testability) so it is easy (cheap) to maintain and your team doesn't require super skilled people to get a decent amount of work done. You may think Radiolistener is full of BS right now, but once you gain more coding experience on larger projects, you'll see that the suggestions made by Radiolistener do make sense (especially when working in bigger teams on large code bases). And if this sounds like a 'lowest common denominator' approach then the message has come across; that is the case. KISS rules.
-
Yet somehow the linux kernel is one of the largest software projects known to human kind, with some of the largest numbers of contributors popping in and doing something. Claiming that it requires extraordinary skills to do so cannot be right.
You can say that it's done in a wrong way and it's utter shit, but then your definition for what is shit is irrelevant, because it produced one of the best software projects known to human kind (relatively to the sheer size of the project and its scope, and number of contributors).
What is "good" and "bad" is matter of taste, but I prefer useful definitions; yes, because Linux kernel works very well, is maintainable in real world, and people come and go and make the required modifications easier than in most other projects, it must mean that code cannot be very bad, for a useful definition of "bad". Yes, it's this simple. I believe in track records and practical results over the opinions of nctnico, sorry.
-
Basically your argument is 'it works, so it can't be bad'. But that is the wrong way to look at it. Linux kernel coding style is like Evel Knievel coding. Only very highly 'skilled' people can write and maintain code like that. Judging by how Linus tends to react to (cancel) people wanting to simplify things you can argue he only likes coding acrobats / stunt people to work on the kernel. The problem is that not everyone is a coding acrobat and stunts tend to go wrong every now and then. Evel Knievel broke many bones in his carreer as a stunt man...
If you lead a team of programmers to work on a commercial project, you will want to lay down some coding style ground rules (like MISRA for example) and probably some additional ones as well to make sure the code has a certain level of quality (as in maintainability and testability) so it is easy (cheap) to maintain and your team doesn't require super skilled people to get a decent amount of work done. You may think Radiolistener is full of BS right now, but once you gain more coding experience on larger projects, you'll see that the suggestions made by Radiolistener do make sense (especially when working in bigger teams on large code bases). And if this sounds like a 'lowest common denominator' approach then the message has come across; that is the case. KISS rules.
I not only think exactly like you, Nctnico, but I also "measured" this matter!
Trying to certify the linux kernel for DO178B: result? not even the E level, the lowest!
And that's enough for me, as there are versions of VxWorks that pass DO178B/LevelA!
-
what is shit is irrelevant, because it produced one of the best software projects known to human kind
It's irrelevant as well as it's irrelevant what *you* consider "best": if we go by objective criteria, well...
... the kernel doesn't even pass level E. And it's not a matter of taste, it's a matter of facts.
(well, it's a matter of budget, to be honest ...
certifing Linux would cost more than buying a full licence of VxWorks/levelA)
I'm not saying that Linux sucks, I'm just saying that *for the industry*
there are objectively better ways to manage a project's code.
Which is what DO178B covers.
-
Only very highly 'skilled' people can write and maintain code like that. Judging by how Linus tends to react
Precisely.
worse, since Robert Love's patches (kernel 2.2-2.4), have split the community in two:
- highly 'skilled' people can write and maintain code like that
- common developers, who are struggling along, with crumbs falling from the table of highly 'skilled' people
A good example is SHARP kernels for the Japanese Zaurus PDAs.
When SHARP paid professionals to develop, fix and mantein the linux kernel (2.4) for the PDA, everything worked fine
When SHARP discontinued the Zaurus... things started to break quickly.
In this, it is not that Zaurus was of interest to only a few hobbyists.
It rather that people with high Linux skills tend not to work on anything that is paid less than 50USD/hour.
And without money, no one, or rather a few people in the whole world, have been able to fix those problems.
It took me more than 10 years to fully fix an old 2.6.23 kernel, and I can't afford anything else on my PDA!
All the other kernels, even the ones that the OE devs worked on between 2005 and 2015, are either totally unstable.
Or don't have working suspend, which on a portable device kills the battery in less than 45 minutes.
-
you'll see that the suggestions made by Radiolistener do make sense
That is a very generous interpretation from words like "However, it is important to understand that by [using goto], you are introducing poor quality shitty-code, and you should be aware of the potential consequences that may arise from it."
That, and its numerous repetitions using slightly different wording, is what I object. As useful as some of Radiolistener's posts are to learners, I am seriously unhappy about how they utterly reject any rational criticisms of their opinions stated as facts. I am unhappy, because it leads others astray. The opinion itself is based on a logical fallacy –– that all uses of goto leads to "poor quality shitty-code" ––, as provably true and easier to maintain patterns with lower occurrence of bugs have already been shown and explained. You can disagree however much you want, but that is an observable fact. Just because you insist on calling the sky yellow doesn't make it so.
And telling someone not very experienced in C to avoid preprocessor macros is just sheer stupidity. They are a very useful tool that when correctly used, makes project maintenance much easier. Before C23, the only actual constants there are are literal constants and preprocessor macros (that preprocess to literal constants), for fucks sake! const does not declare a constant; it is simply a promise by the programmer to the compiler that the code will not try to modify this variable in the current scope, that's all. And if you want to do polymorphism (using e.g. C11 _Generic), like say signbit(x) (https://man7.org/linux/man-pages/man3/signbit.3.html), you have to use preprocessor macros.
Claiming absolute rules like that apply is idiotic and counter to observable reality, and shows that the person hasn't had sufficient experience in diverse software projects, because otherwise they'd know from experience such rules always have their exceptions. Doubling down, and not admitting it, is obnoxious social gaming that I detest, and is why I called radiolistener full of shit.
I compared the Linux kernel to other similar enterprise projects. At the rate it is developed –– so rapid that even the largest companies have trouble keeping up –– its bug density is lower than in any enterprise projects I've seen.
The code you have in projects complying with MISRA-C or DO178B is not so because it is better written from the get go: it is so because it has gone through a rigorous review, test, and verification cycles. Those standards are not coding standards, they are development process standards.
For minimal bug density C code, I did tell you to go look at Dan J. Bernstein's C code; and 5U4GB added Wietse Venema.
This thread went to shit the moment radiolistener told metertech58761 to not use goto and preprocessor macros. It was just utter shit advice, stemming from misunderstanding process-based choices as axiomatic universal truths. The "bad example" in #13 is just laughable: the exact same pattern is extremely useful if you just rename the macro from true to say enable_print.
Instead, we should have told metertech58761 and others reading the thread trying to convert assembly to C without that much experience in C that this intermediate form is not maintainable in long term, and needs to be refactored or rewritten to a more maintainable form without changing the functionality. In fact, that was exactly what metertech58761 was asking: how to go on from here.
All of the patterns shown in the assembly code can be converted to easily maintained while or do..while loops and inlineable/static sub-functions. (In C, "static" and "static inline" have the exact same effect on a function: it will only be accessible from the current compilation unit (typically current .c source file), and the compiler is free to inline the function to its caller, and not generate a callable function for it at all. I use the distinction to help us humans distinguish between internal functions and accessor/helper functions.)
Instead of what not to do, radiolistener and others should have suggested what to do instead. And that applies to you too, Picuino: instead of claiming "X is harmful", you should show that "Y is better than X, because Z".
This is a technical discussion. Telling others "don't do that!" is useless –– no, trolling! –– when better alternatives are not shown.
I have now repeatedly tried to show better patterns, to no avail. In #100 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5871399/#msg5871399), I recap the timeline. In #110 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5873958/#msg5873958), I tried to go back to the interesting stuff, although I was still a bit too emotionally invested to have much thought in the patterns themselves; with #123 (https://www.eevblog.com/forum/programming/converting-assembly-to-c/msg5876616/#msg5876616) showing a better one (splitting the Repeat/Next into a separate function, then combining the rest of the loops into while loops and subfunction calls). No bites. You guys are more interested in nitpicking on what degree of "goto" and preprocessor macros in C can be considered "harmful", than actually looking at the actual code. Nctnico claims to have decades of Linux kernel experience, but still complains how hard it is to fix things with it, especially because things change –– I bet they find the lack of stable internal APIs also a sign of "low quality code", even though the actual reasons are well known. I've done similar work, even just to help other members here, and I just don't find it difficult to work with the Linux kernel code. Perhaps it is because I've worked with all sorts of stuff, and not just regimented centrally-controlled codebases, so I've learned to understand better? In any case, I just cannot take such complaints seriously, because they rationally simplify to "the code is horrible, because any modification I make causes bugs", which is not an indication of the code per se, but one of the programmer at hand.
I keep telling you, making arguments from authority –– be it your work experience or whatever else –– just does not cut it. You need to show the actual better patterns, instead of claim they exist, or worse, just tell others to avoid some patterns without suggesting any replacements. It is not just silly, it makes it very difficult for learners to discern which suggestions to follow. Essentially, you're shittifying the entire thread with your crap.
Stop it. Do like I've done, and suggest something better instead.
-
Basically your argument is 'it works, so it can't be bad'. But that is the wrong way to look at it. Linux kernel coding style is like Evel Knievel coding. Only very highly 'skilled' people can write and maintain code like that. Judging by how Linus tends to react to (cancel) people wanting to simplify things you can argue he only likes coding acrobats / stunt people to work on the kernel. The problem is that not everyone is a coding acrobat and stunts tend to go wrong every now and then. Evel Knievel broke many bones in his carreer as a stunt man...
If you lead a team of programmers to work on a commercial project, you will want to lay down some coding style ground rules (like MISRA for example) and probably some additional ones as well to make sure the code has a certain level of quality (as in maintainability and testability) so it is easy (cheap) to maintain and your team doesn't require super skilled people to get a decent amount of work done. You may think Radiolistener is full of BS right now, but once you gain more coding experience on larger projects, you'll see that the suggestions made by Radiolistener do make sense (especially when working in bigger teams on large code bases). And if this sounds like a 'lowest common denominator' approach then the message has come across; that is the case. KISS rules.
I not only think exactly like you, Nctnico, but I also "measured" this matter!
Trying to certify the linux kernel for DO178B: result? not even the E level, the lowest!
And that's enough for me, as there are versions of VxWorks that pass DO178B/LevelA!
I've seen code, certified to the A level, that anybody with minimal experience will identify as ugly, utter crap, or using a term seen here, shitty. Thus, I do not see the relation between "quality" and "certifiable".
That code worked, so also no relation between correctness and quality. Well, there is a relation, quality code must be correct.
But, such code was hardly maintenable. In fact, sometime later, the company (a big one with government funding) dismissed parts of its codebase and recoded them from scratch, certification of the old code was costlier.
-
you'll see that the suggestions made by Radiolistener do make sense
That is a very generous interpretation from words like "However, it is important to understand that by [using goto], you are introducing poor quality shitty-code, and you should be aware of the potential consequences that may arise from it."
You are taking these claims way too literally. Look at the context instead. Radiolistener obviously works in an environment dealing with extremely large code bases where they probably use code analysis and automatic (unit) test tools (maybe even proprietary ones) and so on. In such environments you need to have strict rules to allow for the review process and code analysis / automated testing tools to work and actually catch potential bugs. Also keep in mind that every different execution path adds an extra test vector and thus testing time. However, in the context of this forum you really should read posts like Radiolistener writes as good advice to create maintainable code. I do. The bottom line is: think about the structure before writing code and don't obfustigate what doesn't need to be obfustigated (like having complex macros for things that are better implemented by a function). Avoiding complex macros and gotos are good mental excersises to get to code which has a better structure.
An example of a project where somebody just started coding without thinking about the structure: Very early on in my career I worked on a large C project for automating paid phone & TV services in hospitals. This software was written by a self thaught 'programmer'. Most was in a single C source file with very few functions. So I ended up printing it (on a matrix printer with continous paper). Even with 100 lines / page I ended up with a big stack of paper and then I annoted all the nested ifs, switches and for/while loops so I could get a sense what the code was doing. But it was clear the guy just started coding in a delerium. I recall needing to make a change to one part which consisted of an entire page of code. So I took out paper and pencil and drew out a flow-chart with the conditions. Subsequently I replaced the 100 lines of code with about 15 lines which did exactly the same + the modification.
-
you'll see that the suggestions made by Radiolistener do make sense
That is a very generous interpretation from words like "However, it is important to understand that by [using goto], you are introducing poor quality shitty-code, and you should be aware of the potential consequences that may arise from it."
You are taking these claims way too literally.
No.
If you were right and I was wrong (about taking claims way too literally), metertech58761 would still be participating in this thread having progress with the task they started this thread for. Because they aren't, and what I've described about how and why the thread fails to help, your interpretation is unrealistic. I posit your stance is based on personal feelings and opinions, and not observable facts at hand.
-
I've seen code, certified to the A level, that anybody with minimal experience will identify as ugly, utter crap, or using a term seen here, shitty. Thus, I do not see the relation between "quality" and "certifiable".
That code worked, so also no relation between correctness and quality. Well, there is a relation, quality code must be correct.
But, such code was hardly maintenable. In fact, sometime later, the company (a big one with government funding) dismissed parts of its codebase and recoded them from scratch, certification of the old code was costlier.
:bullshit:
Given that the "goal of a code" is to satisfy constraints and requirements
For DO178B, in short, the "quality of the code" is a measurement vector that branches out into different aspects
- (1) how efficient it is in time, rapid execution of algorithms
- (2) how efficient it is in space, how much the data structures have been designed ad hoc to occupy the least possible memory
- (3) estimate of how much time it takes to implement and test new features without having to rewrite the code entirely
- (4) how much time it takes to write ad hoc test-cases to verify that the various constraints and requirements are satisfied in the various working conditions, i.e. { "normal", "abnormal", "simulated hw malfunction" }
Plus, what is the probability that, in the case of { "abnormal condition", "hardware malfunctions" }, the code will behave in a way that is dangerous for the mission (level B, C), or mission + crew and pilots(level A);
this involves activities to completely eliminate deadcode, and various points of "defensive code", especially in the "critical" parts - (5) how much time does the QA-team take to analyze the documents produced by { 1,2,3,4 } verifying, on the basis of the test-report documents and various produced, that the constraints and requirements given by the customer are actually respected.
Points 1, 2, 3 quantify the hours of engineering
Points 3 and 4 quantify the hours of testing
Point 5 determines customer satisfaction
Development activities focus primarily, first on design, then on error propagation, then on the final drafting of the documentation that describes these design aspects, finally on the implementation of the "engineering versions" (also known as "draft"), which are passed to the testing team, which produces documents on what is good, what needs to be changed, to minimize testing times!
Feedbacks here have the effect of producing
- much more readable code (to make life easier for the QA team)
- better structured (to make life easier for the testing team)
One of the goal of DO178B is to improve the code lifecycle as much as possible.
Which means making everyone within the various teams able to operate on the code and documentation.
Exactly the opposite of what is on Linux kernel.
Which is much more vertical, concentrating development, and the attention given
to public patches, only to developers with very high skills.
-
I have to decide if I want to pursue this project any further.
Watching a seemingly simple question on the initial stages of the app rewrite, bloom into a hurricane in a thimble, leaves me with zero hope whatsoever for one of the more intricate (and critical) sections of code deeper within. :palm:
-
I have to decide if I want to pursue this project any further.
Watching a seemingly simple question on the initial stages of the app rewrite, bloom into a hurricane in a thimble, leaves me with zero hope whatsoever for one of the more intricate (and critical) sections of code deeper within. :palm:
I don't see why that's an issue. One body of engineers doesn't have to agree with another body.
Some very successful people ask around just to get different opinions, before they make their own decision. You've got the benefit of multiple opinions, no-one deliberately gave you bad advice from what I can see, and just like others in the thread, I too certainly wouldn't agree with all of it either, but you've got the reasonings from people in the comments to make your decisions.
It's quite discouraging to see your criticism (not for the first time I believe) and when you blame your lack of enthusiasm on all the effort from your peers in writing the extensive comments above.
-
I have to decide if I want to pursue this project any further.
Watching a seemingly simple question on the initial stages of the app rewrite, bloom into a hurricane in a thimble, leaves me with zero hope whatsoever for one of the more intricate (and critical) sections of code deeper within. :palm:
I don't see why that's an issue. One body of engineers doesn't have to agree with another body.
Some very successful people ask around just to get different opinions, before they make their own decision. You've got the benefit of multiple opinions, no-one deliberately gave you bad advice from what I can see, and just like others in the thread, I too certainly wouldn't agree with all of it either, but you've got the reasonings from people in the comments to make your decisions.
It's quite discouraging to see your criticism (not for the first time I believe) and when you blame your lack of enthusiasm on all the effort from your peers in writing the extensive comments above.
Yes.
I wonder if the OP has got "better" responses from forums such as stackexchange/stackoverflow etc.
-
I never got around to asking anywhere else. Besides, after seeing the reaction this spawned, people talking over each other, telling me to ignore other posters, etc... how does this help me?
What assurance have I that regulars at any other forum would be any more patient with my approach or questions?
This had always been a 'when I have time' thing. I found a couple other things I hadn't expected to find and which currently have my attention, and other RL tasks are taking priority.
-
I never got around to asking anywhere else. Besides, after seeing the reaction this spawned, people talking over each other, telling me to ignore other posters, etc... how does this help me?
That kind of thing happens all the time, in all walks of life.
One key life skill is working out ways to decide who to trust and to what extent.
Another key life skill is to work out to what extent other people's advice and experience applies to you. If you understand the general fundamentals, then it you are more likely to be able to see how specific tricks and techniques are or aren't relevant.
That's why theoretical and practical experience is valuable - and that takes time to learn.
What assurance have I that regulars at any other forum would be any more patient with my approach or questions?
None whatsoever, of course.