while(1) a very poor construct

Thread Starter

takao21203

Joined Apr 28, 2012
3,702
Everybody is using while(1) in the main loop but to me it looks a poor substitute for goto.

Code:
void main(void)
{
 InitApp();
 LCD_PWR=1;
 
 mainloop:;
 if(prg_flags&PRG_TIMER_FLAG)
 {
  led_ctr++;
  prg_flags&=(0xff-PRG_TIMER_FLAG);
 }
 if(led_ctr==0x60)
 {
  led_ctr=0;
  prg_flags^=PRG_LED_FLAG;
 
  if(!(prg_flags&PRG_INIT_FLAG))
  {
  lcd_init();
  lcd_locate(0);lcd_str("16F884\0");
  prg_flags|=PRG_INIT_FLAG;
  }
 }
 goto mainloop;
}
If for some reason (its a constant) 1 is no longer a true condition, the program will stop working.
 

AlbertHall

Joined Jun 4, 2014
12,346
I would expect most compilers to optimise out the actual check of 1<>0.
OTOH if for some reason 'mainloop' moved to a new address then the program would stop working.
 

joeyd999

Joined Jun 6, 2011
5,285
Everybody is using while(1) in the main loop but to me it looks a poor substitute for goto.

Code:
void main(void)
{
InitApp();
LCD_PWR=1;

mainloop:;
if(prg_flags&PRG_TIMER_FLAG)
{
  led_ctr++;
  prg_flags&=(0xff-PRG_TIMER_FLAG);
}
if(led_ctr==0x60)
{
  led_ctr=0;
  prg_flags^=PRG_LED_FLAG;

  if(!(prg_flags&PRG_INIT_FLAG))
  {
  lcd_init();
  lcd_locate(0);lcd_str("16F884\0");
  prg_flags|=PRG_INIT_FLAG;
  }
}
goto mainloop;
}
If for some reason (its a constant) 1 is no longer a true condition, the program will stop working.

Yes! The while (1) construct has always bugged me wrt embedded programming. But I write in .asm, so I never use it.

There should be a more specific keyword, something like:

Code:
do infinite {
...
}
This better relates the intention of the programmer, I think.
 

Papabravo

Joined Feb 24, 2006
21,225
Everybody is using while(1) in the main loop but to me it looks a poor substitute for goto.
...
If for some reason (its a constant) 1 is no longer a true condition, the program will stop working.
I'm not sure that your opinion enjoys wide support. There are several alternatives including, but not limited to:
  1. for( ; ; ){ .... }
  2. do { .... } until 0>1 ;
  3. while ( 0 < 1 ) { .... }
 

nsaspook

Joined Aug 27, 2009
13,306
I would expect most compilers to optimize out the actual check of 1<>0.
An explicit 'goto' loop for a non-terminating program is a Code smell.

Yes, it would just optimize out the constant condition check in most cases into a asm goto loop. The while loop is also a code block that can be used to scope local variables within that loop from main.

Poor example:
C:
main()
{
 int i=3;
 while(i--){
  int i=100;
  i--;
  printf("%d..",i); // prints 99
 }
}
The while 'i' check uses the main 'i'and printf uses the block 'i'.
 

John P

Joined Oct 14, 2008
2,026
Back when I programmed 8051's in assembly language (those were the days) if I needed an endless loop, the label I always used as a target for the GOTO was KAFKA.

Now I use the MikroC compiler to work pith PIC processors, and I just checked; it does replace the while(1) with a simple GOTO at the end of the loop. No, it doesn't put 1 into the W register and then check the zero flag!
 

WBahn

Joined Mar 31, 2012
30,071
I define a constant or macro at the top of the program, so that I can use the following line:

while (forever)
I have TRUE and FALSE defined for general use, so I generally use

while (TRUE)

Same I idea -- it makes the intent of the code developer explicitly obvious, where as something like

while (1 > 0)

could bring forth thoughts that the developer made a mistake in writing their test.

I don't write very much embedded code any more (and when I did it was all in assembly), but if I ever get back to it I will probably do what you did and add

#define FOREVER (TRUE)

to make the code intent even more obvious.
 

Papabravo

Joined Feb 24, 2006
21,225
under what conditions would 1 be no long true?
If the C standard was to change. I believe it defines false to be 0, and any non-zero value is true.

Like this:
#define FALSE 0
#define TRUE !FALSE

There is also the header file stdbool.h which you can consult for additional styles.

Note that if you do something like:

#define FALSE 0
#define TRUE 1

then a construct like

if(x == TRUE)

might not evaluate correctly if x happened to have the value 2.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,306
When it will not change or can not change there is no purpose testing for it.
That's assumes the C compiler is just a dumb 1 to 1 translator of your code to machine language. The elimination of const condition checks is one of the easiest optimizations to build into that stage of the process. Write your code to be easy to read, debug and maintain, let the compiler do it's job of finding the best way to write the hardware code in all but a few cases that require specialized expertise. The while (1) loop is not one of those cases.

https://en.wikipedia.org/wiki/Constant_folding
Constant propagation can also cause conditional branches to simplify to one or more unconditional statements, when the conditional expression can be evaluated to true or false at compile time to determine the only possible outcome.
 
Last edited:

WBahn

Joined Mar 31, 2012
30,071
If the C standard was to change. I believe it defines false to be 0, and any non-zero value is true.

Like this:
#define FALSE 0
#define TRUE !FALSE

There is also the header file stdbool.h which you can consult for additional styles.

Note that if you do something like:

#define FALSE 0
#define TRUE 1

then a construct like

if(x == TRUE)

might not evaluate correctly if x happened to have the value 2.
The best way to do that is simply

if(x)

since then any value of x that is a logical TRUE will evaluate as TRUE in the if() statement.

Equality testing of logical values in C is fraught with problems since any non-zero value is TRUE. This can be handled by first applying a logical operation to force it into one of the two specific logical values use by the predicate operators. The easiest one is the logical negation. So you could do

if (!x == !TRUE)

That satisfies the purpose, but isn't the most readable of tests. You could patch this with a macro

#define isTrue(x) (!(x) == !TRUE)

if (isTrue(x))
 

Papabravo

Joined Feb 24, 2006
21,225
The best way to do that is simply

if(x)

since then any value of x that is a logical TRUE will evaluate as TRUE in the if() statement.

Equality testing of logical values in C is fraught with problems since any non-zero value is TRUE. This can be handled by first applying a logical operation to force it into one of the two specific logical values use by the predicate operators. The easiest one is the logical negation. So you could do

if (!x == !TRUE)

That satisfies the purpose, but isn't the most readable of tests. You could patch this with a macro

#define isTrue(x) (!(x) == !TRUE)

if (isTrue(x))
You remind me of the song about the daring young man on the flying trapeze - he flies through the air with the greatest of ease. Truly you have a dizzying intellect!
 

MrSoftware

Joined Oct 29, 2013
2,202
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.
 
Top