while(1) a very poor construct

Thread Starter

takao21203

Joined Apr 28, 2012
3,702
while(1) is better than goto in C/C++ because it's easier to read, which makes the code easier to maintain. Code within the while() should be clearly enclosed by curly braces { } and intended, unless your loop consists of only a single line. So it's obvious at a glance exactly what code is included within the loop. With a goto you have to go digging around looking for the target label. And if the intern wrote the code, the loop might contain a bazillian lines of code instead of a handful of function calls. ;)

If the constant "1" suddenly becomes non-true in C/C++, then the while(1) will be the least of your worries.
Correct, it wouldnt really matter anymore. But it reminds me of cobbling together a pointer from 8 bit values (because earlier C compiler was not able to dereference the construct with a baseline PIC as target).

Normally my main loop is with a screen page or two, and I dont use a lot of goto. But there are some instances where it looks more naturally to me. I dislike switch constructs stretching over pages (think of PASCAL language horrors here).
So I use tables whereever Id line up the same function calls many times.

I think from now on I will use the goto variant instead of while(1), even if theres not really a potential for confusion.

A few goto instructions are no problem at all, when their scope is within a short range.

Ive also had a case where the computation for the condition is only possible after processing most of the loop, need to resort to flags (more than one). With a goto, I simply reuse part of the code above, instead of duplicating it again (need to run the actual code first before arriving at the tet condition result).

Its far less lines using a goto and less complicated.

I agree other constructs such as while should be given priority.
 

WBahn

Joined Mar 31, 2012
27,855
There's a reason that the goto statement is in the language -- there are times when it is the most reasonable approach to use. But it should only be used when there is a damn good reason to -- and avoiding a while(1) construct does not qualify as a damn good reason (in my book).
 

MrSoftware

Joined Oct 29, 2013
2,056
There are many options for re-using code blocks without goto. The easiest to read is a function. If stack push/pop times are important then you can use a macro or in-line function. More similar to a goto would be the "continue" statement, which will jump back to the start of any loop. "Break" will jump out.

There are almost always multiple ways to solve any one problem. I'm personally not a fan of goto.
 

WBahn

Joined Mar 31, 2012
27,855
There are many options for re-using code blocks without goto. The easiest to read is a function. If stack push/pop times are important then you can use a macro or in-line function. More similar to a goto would be the "continue" statement, which will jump back to the start of any loop. "Break" will jump out.

There are almost always multiple ways to solve any one problem. I'm personally not a fan of goto.
I'm with you. I personally try to avoid 'continue' and 'break' statements in loops (you are pretty much stuck with 'break' in switch statements) as well, but there are definitely many instances in which these are clearly the preferred constructs both from a writeability and readability standpoint. What I balk at are the numerous times when people throw them at a problem as a convenient kludge when they are NOT a preferred approach and, in fact, detract from clean, maintainable code.

In this same vein is using multiple return statements in a function -- there are times when this is the most elegant and clean approach, and others when it just makes a mish-mash of the logic.

The boundary at which one becomes the other is, of course, in the eye of the beholder and is at the heart of the art of programming.
 

dannyf

Joined Sep 13, 2015
2,197
A large function is generally a sign of trouble.

I also try to avoid multiple return structures. They are tough to track. I use s variable to hold the return value and if there so many possible returns, a state machine is usually a good idea.
 

WBahn

Joined Mar 31, 2012
27,855
I can't tell you how many bugs I've fixed over the years related to multiple return statements in large functions..
Same here. Of course, a large function is a red flag in and of itself. My goal is to, when reasonable, keep functions to a size that let's me display them entirely on one screen without scrolling. That used to be a pretty fixed size, but with today's displays it covers a lot of ground. If I need more lines than that, then it is usually a pretty good sign that I am operating at the wrong level of abstraction and can write that function at a higher level letting it call other functions that work at a lower, but more constrained, level.

Not always reasonable to make this happen, of course. I find that functions implementing state machines are the most likely to become long winded, but the very structure of such functions makes them pretty easy to write in a strict format that makes them easy to maintain even if they are several pages long. First and foremost, I make these functions ONLY operate the state machine -- the actions performed by each state, unless very simple, are done via a call to an appropriate function. I figure that the level of abstraction appropriate to most state machines is best constrained to just the operation of that machine.
 

MrAl

Joined Jun 17, 2014
9,623
Hi,

I was a little baffled as to why someone would not like:
while (1)
{
dothis();
dothat();
}

The points i saw brought up so far dont seem to discredit the use of this idea in any reasonable way.

For one, there's no way that '1' can change to a zero '0' unless the program goes berzerk.
For two, using a goto means you'll have to find another way out of the loop which also is not that great of an idea, such as another goto. I say this because it is not that often that we see a while statement used as the only statement where once the program is done we jump out. That would certainly not be the norm. The norm would be using a while statement for a temporary loop that we eventually want to exit from in a relatively short time.

Not only that, but it helps with the readability to use integers as the following simplified code illustrates:

Try reading this first (assume the while loops all exit after one pass):
while (1)
{
dothis();
while(1)
{
dothat();
while (1)
{
dosomethingelse();
}
dosomethingentirelydifferent();
}
a=1;
check1();
}
b=2;

now try reading this, the same functionality as above:
while (1)
{
dothis();
while(2)
{
dothat();
while (3)
{
dosomethingelse();
} //3
dosomethingentirelydifferent();
} //2
a=1;
check1();
} //3
b=2;

note how the numbers 1,2,3 make it almost self documenting.
It even helps when the code is typed out as normal 'code' like we usually do, and note this is short but often a code segment with a while loop is longer too...
Code:
while (1)
{
  dothis();
  while(2)
  {
    dothat();
    while (3)
    {
      dosomethingelse();
    } //3
    dosomethingentirelydifferent();
  } //2
  a=1;
  check1();
} //3
b=2;
 
Last edited:

WBahn

Joined Mar 31, 2012
27,855
For two, using a goto means you'll have to find another way out of the loop which also is not that great of an idea, such as another goto. I say this because it is not that often that we see a while statement used as the only statement where once the program is done we jump out. That would certainly not be the norm. The norm would be using a while statement for a temporary loop that we eventually want to exit from in a relatively short time.
I think you are missing the point that the while(forever) loop is often THE program in an embedded system. When do you want your watch to stop running? You don't! Or, think of your operating system. You want it to ideally run forever. How do you make this happen? By putting the entire O/S program into an infinite loop!
 

MrAl

Joined Jun 17, 2014
9,623
I think you are missing the point that the while(forever) loop is often THE program in an embedded system. When do you want your watch to stop running? You don't! Or, think of your operating system. You want it to ideally run forever. How do you make this happen? By putting the entire O/S program into an infinite loop!
Hi again,

Oh i see, well if that's the case i dont know if i would use a while loop then.
I'd have to think on this one some more as i dont usually have to do this.
I know in PIC asm i just use a label and goto.

Start:
dostuff()
goto Start.

I'd probably do that in C also. It's clear enough due to the label name.
 

Papabravo

Joined Feb 24, 2006
19,564
There is no sense arguing this point further. If your head is in assembler you'll never appreciate the benefits of structure. If your head is not in assembler than who cares.
 

ErnieM

Joined Apr 24, 2011
8,346
Hi,

I was a little baffled as to why someone would not like:
while (1)
{
dothis();
dothat();
}

The points i saw brought up so far dont seem to discredit the use of this idea in any reasonable way.

For one, there's no way that '1' can change to a zero '0' unless the program goes berzerk.
For two, using a goto means you'll have to find another way out of the loop which also is not that great of an idea, such as another goto. I say this because it is not that often that we see a while statement used as the only statement where once the program is done we jump out. That would certainly not be the norm. The norm would be using a while statement for a temporary loop that we eventually want to exit from in a relatively short time.

Not only that, but it helps with the readability to use integers as the following simplified code illustrates:

Try reading this first (assume the while loops all exit after one pass):
while (1)
{
dothis();
while(1)
{
dothat();
while (1)
{
dosomethingelse();
}
dosomethingentirelydifferent();
}
a=1;
check1();
}
b=2;

now try reading this, the same functionality as above:
while (1)
{
dothis();
while(2)
{
dothat();
while (3)
{
dosomethingelse();
} //3
dosomethingentirelydifferent();
} //2
a=1;
check1();
} //3
b=2;

note how the numbers 1,2,3 make it almost self documenting.
It even helps when the code is typed out as normal 'code' like we usually do, and note this is short but often a code segment with a while loop is longer too...
Code:
while (1)
{
  dothis();
  while(2)
  {
    dothat();
    while (3)
    {
      dosomethingelse();
    } //3
    dosomethingentirelydifferent();
  } //2
  a=1;
  check1();
} //3
b=2;
The code fragment at the end shows the importance of white space, the indentations that make each block jump off the page at you. That makes the closing bracket comment quite redundant, especially on short sections of code. (When I have along section of code then I will typically add a closing comment, but this is mostly for header files.)

What is interesting about the fragment is it will dothis() once, dothat() once, then dosomethingelse() forever, and never does dosomethingentirelydifferent(). Such is the power of infinite loops.
 

MrAl

Joined Jun 17, 2014
9,623
The code fragment at the end shows the importance of white space, the indentations that make each block jump off the page at you. That makes the closing bracket comment quite redundant, especially on short sections of code. (When I have along section of code then I will typically add a closing comment, but this is mostly for header files.)

What is interesting about the fragment is it will dothis() once, dothat() once, then dosomethingelse() forever, and never does dosomethingentirelydifferent(). Such is the power of infinite loops.
Hi,

Yeah sorry but you did not read my post in it's entirety.

For one, i said assume that all loops exit as usual.
Second, i said that the comments like //3 are helpful WHEN the code fragments are long, and that means they run off the page of the editor you are using without code folding.

To give you a better idea how this works, you never see while(1), all you see is this:

doone();
dotwo();
c=5;
d=c+d;
}

and so as to not have to type 25 lines of code that is all you see in your editor because of the line you have scrolled down to.
There may be indents, but you cant count indents reliably when there are 4 to 6 or more spaces and some people use 4 spaces per indent so that could be 8 to 12 spaces in front of all those lines above. So the question is, which while statement is the code above in.

Now with the comments you have this:

doone();
dotwo();
c=5;
d=c+d;
} //3

and so you see you are within the third while statement not the first or second.

There is no way to know where you are in the code without context sensing however, so if you can only see:

doone();
dotwo();
c=5;

then you still dont know what while statement you are in without scrolling up or down, but if you dont use the //3 comment then you can only scroll up not down in order to see where you are in the loop context.

This is the same with function declarations as in this pseudo language:
function MyFunc1()
a=1;
b=2;
c=3;
end function

If you have a large function body you may not be able to see the "MyFunc1()" or even the "end function" as you might just be able to see part of the body without scrolling:
b=2;

My editior happens to be able to sense this context however, and displays at the bottom of the screen:
"MyFunc()"

and that happens as i scroll anywhere between the lines "MyFunc()" and "end function". Once i scroll out of that region, it either displays "Top Level" or another function name if within another function body.

This is because i did not yet implement for loop/while loop context sensing which would display something like this:
"MyFunc()", "while 1"

for the context. I was too busy doing other things like adding schematic drawing to the editor :)

But please remember you can do it any way you want to, you dont have to do it this way, and you can maybe even invent your own way of doing ti.

I find that code bodies that are longer than about 20 to 25 lines or so present a problem where if you go away from your computer for a minute (such as to get a cup of coffee or a tank of beer (har har)) then when you come back you forget where you have scrolled to in a larger program, and a little reminder at the bottom of the page does help.

I started doing the while 1, while 2, while 3 thing a long time ago, and also comment my for loops too such as:
for(k=1;k<10;k++)
{
dostuff();
}// k

That way nested for loops have the same documentation which does help for more complex loops.

The other issue:
DId someone mention multiple return statements?
This has made me think too, as well as file open/close statements because sometimes a file opening is dependent on something else like even another file opening, and if we return before we close a file we eventually get an error or something.

In pseudo code:

a=OpenFile(path1);
if (x==1)
b=OpenFile(path2);
close(a);
close(b);

File path1 or path2 may not have opened properly in the first place.

I have also used a variable like "retv" to log the return value at the end of several lines of code:
if(a==1)
retv=4;
if(a==2)
retv=5;

return retv;

rather than:
if(a==1)
return 4;
if(a==2)
return 5;

That's a very simple example again so it does not look like it makes much difference, but once the code gets more complicated it starts to make sense to be more careful with where the function returns.
 

ErnieM

Joined Apr 24, 2011
8,346
I cannot agree with the complete lack of white space here. I don't care if you use 4 or 6 or whatever spaces per tab (just don't use the tab character itself) (it doesn't transport well) but well spaced code is a pleasure to read and follow, and you can always mouse wheel up and down to see how thigs interact, even without code folding.

While I have done similar things with multiple return values I would call the value "retail" to make it less cryptic (you have 32 unique characters per liable, use them!) I would never use magic numbers like that. An enumeration type is far better as you generally care more about the meaning of a number over the value. Plus they get tucked nicely into your header file so the meaning is also exportable.
 

MrAl

Joined Jun 17, 2014
9,623
Hi,

I always use white space AND the enumerations, i just left out the white space here for illustration purposes.

I found myself mouse wheeling far too much that's why i started this back then.
It's not just that though, after i do a 'search' for a keyword it often takes me into the middle of some code where it is nice to know where you are without having to mousewheel up and down.
 
Top