C programming loop question main() vs. while(1)

Discussion in 'Programmer's Corner' started by ke5nnt, Mar 24, 2013.

  1. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Just a quick question with a simple answer I hope. Does the void main() function continuously loop like the while(1) function does, or does it run through and then stop?
     
  2. tshuck

    Well-Known Member

    Oct 18, 2012
    3,531
    675
    Depends on the processor. For embedded devices like microcontrollers, the behavior is undefined, it may, or may not, return to the first instruction location. This is why each program should have an infinite loop, so as to keep the behavior deterministic.
     
    absf likes this.
  3. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    IF you exit main() at the bottom, the code returns to the C startup runtime (provided by the compiler). Usually, it cleans up and calls main again. Doing this is probably bad form in an embedded system since there is no 'operating system' to return control to (as would be the case on a PC etc.) and you are depending on the compiler to do your housekeeping..

    Best to put a while(1) in main for embedded systems.
     
    absf likes this.
  4. ke5nnt

    Thread Starter Active Member

    Mar 1, 2009
    384
    15
    Thanks guys, well explained.
     
  5. @android

    Member

    Dec 15, 2011
    178
    9
    Simple main()function doesn't require a specific keyword or procedure for ending the program. In some programming languages, an END or EXIT command is required, but not in C. In the C language, the program ends when it encounters the last brace in the main() function. Hence in C main is not an infinite function. Wherein while(1) is an infinite loop.

    Hope that helped! :)
     
    absf likes this.
  6. WBahn

    Moderator

    Mar 31, 2012
    17,720
    4,788
    This is not necessarily the behavior in a non-hosted implementation, such as is often the case in embedded systems. See the earlier post by JohnInTX for a good description.
     
    absf likes this.
  7. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    Returning from main by automatic means, not doing it on purpose, is a very bad programming style.

    It is not done normally.

    Leaving aspects undefined means you also in general increase the chance for such aspects to show their creepy effects.

    If you have an operating system of any kind, yes, usually programs end at some point.

    In C if you exit from main, at best you will do all the initialization again.

    It is no difference for trivial programs, but larger programs will behave weird if the processor resets all the time.

    You may get correct reactions for some part of the software, and sometimes display flickering.

    Larger programs really don't work that way, as they use storage to determine further behaviour.
     
  8. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Not that I would ever recommend exiting the main() function in a micro for any event except power OFF but it was bothering me to see the behavior referred to as "undefined," which to me means "I didn't look it up."

    So I looked it up. Inside the C18 User's Guide (hlp18ug.chm) there is a section on the start-up code:

    So by the well defined behavior (of this particular compiler) the start-up code is NOT run again if you drop out of the main() function.

    One should leave one brain cell in active storage with this information in case the day comes when your program does weird things because of this very condition.
     
  9. @android

    Member

    Dec 15, 2011
    178
    9
    Looking at the question he posted I think it fits. He is not specifically asking about an embedded application. It is a general question so I gave general answer. :p
     
  10. takao21203

    Distinguished Member

    Apr 28, 2012
    3,577
    463
    I have not seen it often, if at all.
    If there is a programmed exit, it is done with a return, or with a special System function.
     
  11. WBahn

    Moderator

    Mar 31, 2012
    17,720
    4,788
    Ah, no. A general answer would apply both to hosted and non-hosted applications.

    And the question makes much, much more sense if it is being asked about a non-hosted environment. I've never heard anyone working in a hosted environment who thought that main() would behave the same as while(1).
     
  12. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    How one exit's the main function is system dependent: it depends on the definition of main itself.

    Is it:
    void main (void); // typical for C in an embedded system

    or is it:
    int main(void); // PIC32 C, also for embedded systems

    or perhaps:
    int main(int argc, char *argv[]); // typical for C on a Unix system

    In any case, a closing bracket } ends the main function, and if the code drops thru to that then main ends. The compiler will type check any return value if there is a value, but it does not check what is not there: you need not have a return statement in main.
     
  13. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    I took a look at some listings for various compiled code I still have laying around to see what happens when you hit that closing bracket in main():

    C51 - Franklin C for 8051 - Does an LJMP to main. No returning from there

    C80 - Aztec C for 8085/Z80 - Depends on which startup is linked. One JMPs to main, another calls main but just does a RETurn after that. Presumably, some restart vector is on the stack (but I didn't see it). The CP/M library does a system call to start main and an exit(0) at main's end to return to the OS. This is classic DOS/UNIX/VMS etc behavior, passing back an error code as well.

    X6063 (Archimedes) - Calls main and returns to the startup code which does another return.. to the BUFFALO monitor! Presumably, we were using BUFFALO at the time.

    PV32 - Early Kiel / Franklin IDE based 8051-class compiler. Basic startup LJMP to main. No return. The replacement startup code for the target (a handheld terminal) included a jump back to start should main return.

    HI-TECH PICC18 8.35_PL3 Always GOTOs main (to save stack per the manual). If main is contained by a looping construct (while(1) etc), that's it. If NOT, the compiler appends a GOTO back to the startup at the end of main, presumably to restart the program.

    XC8 PIC10Fxx When no while(1):GOTO main to enter, GOTO 0 when exiting main.

    XC8 PIC18Fxx GOTO main to enter. With/without while(1), appends a GOTO start to the end of main.

    Those older compilers weren't as smart as newer ones e.g. PICC18 examines the code flow and tacks on a GOTO startup if you don't have a loop construct in main. It saves the code if you do. Of note is how all of the uCHIP compilers jump into main and jump back to startup to save stack. Smart.

    Those early ones came with the STARTUP source so that you could adapt it to to the target environment e.g. BUFFALO monitor, for even more variances.

    I can't envision a situation where, even if it were documented, I would want to exit main in an embedded system. What then? A well behaved system like HITECH, XC8 or MPC will restart the system mainly because it has nothing else to do with it. To the user, this looks like a reset BUT none of the code I looked at did any system cleanup such as reinitialize the peripherals or set the stack pointer. (To be fair, I didn't look that close but on baseline/midrange PICs you can't even access the stack pointer..). But, rather than exiting main to restart the program in the event of an unrecoverable error etc., I find it best to use the 18F 'reset' instruction or in the lower PICs, hang the watchdog to get a clean, all systems reinitialized restart.

    With of all of this as well as the excellent points made by other posters here describing different possibilities, I stand by my original post; For typical ROM-based, no OS embedded systems, always have a loop construct in main and don't rely on the compiler generated startup code to save your bacon.
     
    Last edited: Apr 3, 2013
  14. Eng Mohamad Yahya

    New Member

    May 28, 2016
    4
    0
    the problem is so simple ,,,, disable the watchdog counter ,,,, that is all :)
     
  15. JohnInTX

    Moderator

    Jun 26, 2012
    2,341
    1,024
    Welcome to AAC. You have replied to an old thread so it is unlikely the original TS is still looking for an answer.
    That said, the watchdog timer would not have anything to do with the original problem of what happens if you don't loop in main() in an embedded system. If anything, you would want the watchdog ENABLED so that if the C runtime does not recover after exiting main(), the processor could be reset when the watchdog times out and restart the system.
     
    ErnieM likes this.
  16. BobaMosfet

    Active Member

    Jul 1, 2009
    109
    11
    main() is a function, whereas while() is a statement. The two things are viewed differently by the compiler and ultimately the processor.
     
  17. Papabravo

    Expert

    Feb 24, 2006
    10,137
    1,786
    Without a looping construct inside of the main() function it will return after executing the last statement before the closing curly brace. What happens next is compiler dependent. You have to locate and examine the C Startup file that is part of every embedded C program. From that assembly language file you can determine exactly what will happen. No general purpose answer will be accurate or reliable; you must dig (excavate(?)) for the answer.
     
  18. BobaMosfet

    Active Member

    Jul 1, 2009
    109
    11
    Not sure why you are replying to me. All I stated was that a function and a statement are different from one another, since the OP didn't seem to know this. Discussing entry points, stack frames, jump tables, and assembly language is well beyond what the OP needs at this point.
     
  19. WBahn

    Moderator

    Mar 31, 2012
    17,720
    4,788
    I don't think PB was so much replying TO you as much as just expanding on the information provided BY you -- and the point he is making is very relevant in a non-hosted environment, which if I recall (from three years ago) the TS was working with at the time.
     
  20. Papabravo

    Expert

    Feb 24, 2006
    10,137
    1,786
    This is precisely the case. I have had occasion to dissect several C startup files for about a dozen embedded processor/compiler combinations. IMHO the ones that do the best job actually force a hardware RESET by hook or by crook when there is a return from main. In most cases it is essential to draw as much attention to this behavior as possible. That said I can imagine a mission critical application in which a softer recovery mechanism might be employed. It is ALWAYS to the benefit of the embedded engineer to understand precisely what the canned compiler code is doing to(for) you. Only in that fashion can you inoculate yourself and your code.
     
    nsaspook and JohnInTX like this.
Loading...