#16
  1. Left due to despotic ad-min
    Devshed Beginner (1000 - 1499 posts)

    Join Date
    Jun 2003
    Posts
    1,044
    Rep Power
    14

    C/C++ jargon: undefined, unspecified, and implementation defined behaviour


    [If/when I get around to setting up a web page, I'll place the text here into that, and this message will simply contain a link.]

    This post is concerned with describing some common terms used by the C/C++ community. The meanings are firmly enshrined in the C and C++ standards, and are relevant to those of us who are keen to ensure our C or C++ programs run correctly on a range of target platforms, when compiled with different compilers.

    Native English speakers, and even Americans (who speak one of the strangest dialects of English), often bang their desk and insist these definitions are wrong, often bringing out a conventional dictionary to support their argument. That's as may be: these definitions are relevant only to those of us who write in C or C++, not to any other English speaker. If you don't wish to program in C or C++, you do not need to use these definitions. But if you do, and you don't wish to have C/C++ gurus accuse you of not understanding what you're talking about, then you had better understand these terms. One thing to remember is that some companies, when recruiting C/C++ programmers, ask questions designed to test your understanding of these concepts and ability to grasp their significance. Why do they do this? Because they care about writing portable and correct code and a programmer who doesn't understand these terms probably has little experience in writing code portably and correctly. I recommend you do not debate these definitions with your loved ones, unless they are C/C++ programmers or are very tolerant of your foibles (or both). But understanding these terms is a basic step in becoming a professional C/C++ software engineer (or geek to the masses) rather than a clueless hacker.

    I would assume the phenomenon of C/C++ speak vs the spoken language occurs with other spoken languages (French, Danish, etc). I pick on English because I speak it.

    OK; on with the definitions. These are lifted straight from the C and C++ standards (in all versions to date). They are interrelated.
    undefined behavior:
    behavior, such as might arise upon use of an erroneous program construct or erroneous data, for which this International Standard imposes no requirements. Undefined behavior may also be expected when this International Standard omits the description of any explicit definition of behavior. [Note: permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. ]
    What does this mean? It basically means that the standards describe code as resulting in undefined behaviour if there is no limit on what happens when the code is compiled and executed. Two common examples are shown here ...
    PHP Code:
      /*  first example */
      
    int *NULL;
      *
    42;

      
    /* second example */

       
    char x[5];
       
    strcpy(x"More than five bytes, including terminating zero"); 
    In practice, compilers are completely silent when code does this, and what often happens is an abnormal program termination (eg a core dump under unix, a general protection fault under windows). However, such a program crash is only one possibility. In theory, your computer could also give you, the programmer, an electric shock when it executes this code (it is perhaps unfortunate that undefined behaviour does not result in a programmer receiving electric shocks: undefined behaviour is one of the largest causes of unexplained software bugs and a significant proportion are caused by programmer carelessness).

    Why do the standards allow such things? The above examples are constructed so it is obvious what is happening. However, in complex code where variables are shared or passed between functions, it is technically VERY difficult (and in some cases, where data may be read from files at run time, impossible) to detect.

    A compiler (or run time environment) that could detect all instances of undefined behaviour, in general, would be both expensive and run slowly. Programmers tend to insist on things like inexpensive compilers, fast compile times, minimal memory footprints, and fast execution of their code. Detecting all cases of undefined behaviour would compromise those things.

    Most real-world examples of undefined behaviour encountered in practice are some sort of problem with pointers. Have a look at Dawei's page on pointers (a link is in an earlier post in this thread) for more details of common mistakes people make with pointers.
    unspecified behavior behavior, for a wellformed program construct and correct data, that depends on the implementation. The implementation is not required to document which behavior occurs. [Note: usually, the range of possible behaviors is delineated by this International Standard. ]
    Unspecified behaviour is like undefined behaviour, except that the standards impose some constraints on what is allowed to happen. However, those constraints do not result in only one possible action. An obvious example, with f(), g(), h(), and i() being functions, is the call
    PHP Code:
       f(g(), h(), i()); 
    In this example, the standard requires that g(), h(), and i() will be called and their return values then passed to f(). However, and the reason this call yields unspecified behaviour, is that the standard does NOT specify the order in which g(), h(), and i() will be called. Some compilers will call g() first and i() last. Some compilers do it in reverse order. In theory, a really smart compiler could do all three calls concurrently, by executing each on a different CPU.

    The reason for such freedom to compiler writers is to allow performance optimisations on a range of target operating systems and hardware. In other words, allow the compiler writer to decide the best order to do things.

    Note: in this example, if one cares about the order in which g(), h(), and i() are called, one can do;
    PHP Code:
    int grethretiret;
    gret g();
    hret h();
    iret i();
    f(grethretiret); 
    as the compiler is required to not reorder the function calls in this case. The code does not rely on any form of unspecifed behaviour to work correctly.

    implementation defined behavior behavior, for a wellformed program construct and correct data, that depends on the implementation and that each implementation shall document.
    Common examples of implementation defined behaviour include the bit layout of integer and floating point types, and how operations like addition are implemented. These are things the implementation (i.e. compiler and libraries) are required to define, but different implementations are allowed to do these things differently.

    sizeof(int) is an example of an implementation defined value. With older 16 bit compilers, sizeof(int) was often 2. With modern 32-bit compilers, sizeof(int) is often 4.

    Why is all the stuff above relevant?

    A lot of questions in various C and C++ bulletin boards (including this one) amount to throwing a bit of code on the table and asking why it doesn't do what the person asking the question thinks should have happened.

    In the vast majority of cases, the cause of a program crash is often some form of undefined behaviour, so the quick -- and correct -- answer is usually to highlight the offending line and make some statement that this is undefined behaviour. The main reason I wrote this post is that a common counter-response to this is "huh", and wasted time/bandwidth expanding on the explanation.

    I have also seen cases where people insist "unspecified behaviour" is actually "undefined behaviour". That may be literally true in the English language, but the language of C and C++ is subtly different and basically shows the person involved as being more interested in proving they are "right" rather than understanding the message that people are giving them by choosing one word rather than another.

    Keep in mind that professional C and C++ programmers who happen to be native English speakers speak about C and C++ in a language that is not actually English, despite having a lot in common with English. This is simply professional jargon. If you want to offer proof that you don't understand C or C++, you will speak only in English!!

    If you want something more concise than this post, have a look here (link courtesy of nnxion). For an example of the type of debate that really "inspired" this post, look here (link provided by InfoGeek)
    Last edited by grumpy; May 21st, 2005 at 09:42 PM.
    It is only our bad temper that we put down to being tired or worried or hungry; we put our good temper down to ourselves."
    -- C.S. Lewis

    I like long walks, especially when they're taken by people who annoy me.
    --Fred Allen
  2. #17
  3. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    244
    Not to belabor the point, but each specialty has its own vocabulary, often using words and phrases that have very distinct meanings within the specialty but just as often fuzzy, indistinct and/or contradictory meanings outside. As I developed expertise in the specialty of information science (of which programming in C/C++ is but a small part) I found reading the 'Jargon Dictionary' to be a very useful apportionment of my time. I suggest that any newbies here (indeed, anyone who has not yet made the time to read such a dictionary) would also find reading the dictionary time well spent. Below are a couple of probably hundreds of different links to various editions of 'The' Jargon Dictionary, a google of 'jargon dictionary' will turn up thousands more (of course not all are IT related, we aren't the only ones who opacify language, try reading some of the MBA jargon if you want a headache).

    http://www.catb.org/~esr/jargon/
    http://www.eps.mcgill.ca/jargon/jargon.html <-- all in a single HTML page, not for those of you on dialup!
    http://www.lysator.liu.se/hackdict/s...ain_index.html
    http://www.science.uva.nl/~mes/jargon/

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  4. #18
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2005
    Posts
    88
    Rep Power
    12
    If you want to know how to make viruses trojans or anything of that nature DON'T ask in this forum. Search google or something.

    Comments on this post

    • codergeek42 agrees
  6. #19
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2006
    Location
    Israel
    Posts
    66
    Rep Power
    0
  8. #20
  9. Google Relay Server
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Oct 2003
    Location
    Oh christ I don't even know any more.
    Posts
    1,812
    Rep Power
    438

    Pointers


    A weird but informative video illustrating how pointers work, originally posted by para45 (hope you don't mind):

    http://cslibrary.stanford.edu/104/

    There are other useful links on that site, including a really nice introduction to pointers and memory in a printable, PDF format.

    Here is what seems to be an informative thread regarding good C/C++ programming books.
    Last edited by peenie; July 10th, 2006 at 09:51 AM.
    OMG RAVER CHICKS!!
    On a related note: C/C++ Programming Tutorials


    "Science is based on reality staying the same, and Nature ignores what humans vote upon." -- Bill Beaty
    "Three litres of sherry up the butt can only be described as astounding." -- Darwin Awards
  10. #21
  11. No Profile Picture
    Redpill
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Nov 2005
    Posts
    1,660
    Rep Power
    151
    I tried to print the reslt of 2 ^ 8 but it gives nonsense. Why?

    Because ^ does not mean "power", as you math fanboys would be used to. It's the XOR operation, which is one of many bitwise operations in C/C++ you should look out for.


    PS: Eeh... (chews carrot) when's yer gonna put up them chappters three an' feur, doc?

    You know guys, if anyone ever asks this again just redirect them to this post; it's much faster than slowly typing out a reply for every newbie idiot out there who can't be bothered to google.
    Last edited by jafet; August 30th, 2006 at 06:02 AM.
    Code:
    #include <stdio.h>
    int main(int o,char**O){return o>-1?o-2||!main(-1,1+O)?!!fprintf(stderr,"%s [0-"
    "9]{81}\n",*O):main(-83,++O):o>-83?(*O)[-1-o]?81==(o=-o-1)||o[*O]<'0'||'9'<o[*O]
    ?0:main(-2-o,O):o==-82:o>-164?(*O)[-83-o]<'1'?main(o-82,O):main(--o,O):o+164?o>-
    246?(*O)[-165-o]<'1'?main(o-82,O):main(--o,O):o+246?o>-328?(*O)[o=-o-247]<='8'?(
    main(-328-o,(++o[*O],O)),main(-247-o,O)):!(o[*O]='0'):(o=-o-328)<729?(o%9/3*3-o%
    27+o/243*9+o/81%3&&(*O)[o%81]==(*O)[o%81-o%27+o%9/3*3+o/243*9+o/81%3])||(o%81-o%
    9-o/81*9&&(*O)[o%81]==(*O)[o%9+o/81*9])||(o/81-o%9&&(*O)[o%81]==(*O)[o%81-o%9+o/
    81])?0:main(-409-o,O):main(-165-o%81,O):!puts(*O):0                           ;}
  12. #22
  13. Making a mistake is not sin.
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2005
    Location
    Finland
    Posts
    406
    Rep Power
    209
    EDIT1:
    Sorry. I wrote another namespace guide.. I did not notice the previous one... please remove this :/

    EDIT2:

    @Grumby:

    Perhaps you could add the explanation why .h ending headers should not be used with modern compilers in your namespaces post? (It is related to that since old .h headers contained thingies declared in GLOBAL namespace, aor actually abowe any namespace. When C++ standard was updated, those thingies were declared in headers without .h (like <string> not <string.h>))
    Now many people seem to be asking why their good 'ol code does not compile with newer compilers.. Some of them notice warning that iostream.h is deprecated and iostream should be used instead (I believe some version of GCC gave that information). Now when user removes .h, he get's warnings about couts, strings, ifstreams etc. being undeclared... (Of course, because namespace is not given).
    Last edited by Mazzie; October 12th, 2006 at 07:27 AM.

    http://c-ohjelmoijanajatuksia.blogspot.com/
    http://maz-programmersdiary.blogspot.com/
    Admitt you do not know - and become wise.
    Pretend to be wise - and stay stupid.
  14. #23
  15. Google Relay Server
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Oct 2003
    Location
    Oh christ I don't even know any more.
    Posts
    1,812
    Rep Power
    438
    Originally Posted by peenie
    A weird but informative video illustrating how pointers work, originally posted by para45 (hope you don't mind):

    http://cslibrary.stanford.edu/104/
    How convenient, here's the video, you can watch it right in this post (just press play; turn sound on):

    OMG RAVER CHICKS!!
    On a related note: C/C++ Programming Tutorials


    "Science is based on reality staying the same, and Nature ignores what humans vote upon." -- Bill Beaty
    "Three litres of sherry up the butt can only be described as astounding." -- Darwin Awards
  16. #24
  17. No Profile Picture
    Contributing User
    Devshed Loyal (3000 - 3499 posts)

    Join Date
    May 2004
    Posts
    3,417
    Rep Power
    887
    About main()

    The C/C++ standards require that a hosted program[1] must have a main(). Unless otherwise specified, the following content addresses hosted programs.


    Code:
    int main(void) ;
    int main( int, char**) ; /* Equivalent to int main( int, char*[] ) */
    NOTE: char** is pointer to pointer to char. More on this later.

    Any function named main should have one of the above signatures. The standard requires that your program have one and only one such function. Some compilers will allow void return type. On Windows systems, some compilers will let you declare wmain() or tmain() instead of main(). Embedded (non-hosted) systems compilers often have their own specs and sometimes allow you to specify a function name other than main. These alternaives are all non-portable because conforming compilers are not required to accept them.

    NOTE: It is a convention that the return value from main(), if any, be non-zero to indicate an error and zero for non-error execution. This is by no means an absolute requirement, but adherance to this convention in the absense of any substantive reasons to do otherwise is strongly recommended.


    The above are only declarations however. To make your linker happy, you have to implement a function named main with one of the above signatures. This is because the c-runtime calls main() after performing some initialization (more on this later). The simplest you can get away with is:

    Code:
    /* Both standards */
    int main( void ) { return 0; }
    That is a pretty useless program, but this is about main() and we're trying to keep it simple. What you do in your main() is mostly up to you.

    If you need to process the arguments passed to your program it gets a bit more complicated:

    Code:
    int main( int argc, char *argv[] )
    {
        /* argc is number of non-null pointers in argv */
        /* argv is array of pointers to c-strings (nul terminated character arrays) */
        /* the last element in argv is always a NULL pointer */
        /* The size of the argv array is (argc + 1) * sizeof(char*) */
        /* sizeof( argv ) is always sizeof( char**) which on 32 bit systems is 4. */
        /* argv[0] is the name of your program */
        /* Your arg handling routines go here */
        return what-ever ;
    }
    NOTE: The argument names argc and argv are conventional but not required by the standard. You could just as easily call them fritz and fraq.

    Now, this is where it often gets confusing for beginers and even us old-timers have to pause momentarily to gather our wits. By convention argv[] always has two elements in it! Even when argc is one!! In fact, argc is always at least 1 (well on most operating systems that supply a command line anyway). This is where I must diverge to talk briefly about arrays and c-strings...

    Except for string literals, there is no special type in C for strings as there is in other languages (C++ does have std::string but that is not relavent to this topic). We simply use character arrays. A "c-string" is an array of characters that by convention is terminated with a nul character ('\0'). All string literals in C are c-strings, but string literals are also special because they can be used to initialize other arrays. A pointer to c-string is a pointer that points to the first element of a nul-terminated character array.

    Code:
    const char lit[] = "string literal" ;   /* compiler automatically nul terminates these */
                                            /* sizeof(lit) == strlen(lit) + 1 */
    const char *pLit = "string literal" ;   /* nul terminated by compiler */
                                            /* sizeof(pLit == sizeof(char*) == 4 on 32 bit system*/
    const char oops[3] = "string literal" ; /* Error: compiler complains that oops isn't big enough */
    NOTE: sizeof(lit) != sizeof(pLit). This is important to remember. The compiler can't tell you how many characters pLit points to, but always knows how many characters are in lit because it is an array. strlen() on the other hand can determine the length of a c-string, but not the length of an un-terminated character array. If oops[] in the above example were initialzied with {'a','b','c'} it would NOT be a c-string and strlen( oops ) would probably crash your program!

    C arrays are "zero based". That is arr[0] is the first element of the array, not arr[1]. A declaration like int arr[N] results in N elements being allocated by the compiler.

    Code:
    const int aBufSize = 3 ;
    int a[aBufSize] ;
    for ( char idx = 0 ; idx < aBufSize ; idx++ )
    {
        a[idx] = idx + 1 ;
    }
    The above code fills a[] with the integer values 1,2,3.

    For int main( int argc, char **argv ), the compiler does not know how big the argv array is but argv[] is always terminated with a NULL pointer. That is; the last element in the argv array is always NULL. argc is always the count of non-NULL pointers in argv[], NOT the number of elements in argv. So you could ignore argc:

    Code:
    int main( int argc, char **argv )
    {
        int MyNonNullElemCount = 0 ;
        char **pArgs = argv ;
        while ( NULL != *pArgs )
        {
            MyNonNullElemCount++ ;
            pArgs++ ;
        }
        printf( "argc: %d\nMyNonNullElemCount: %d\nReturn: %d\n", argc, MyNonNullElemCount, MyNonNullElemCount != argc ) ;
        return MyNonNullElemCount != argc ;
    }
    The above program prints argc, the final value in MyNonNullElemCount and the return value, then returns a non-zero value if MyNonNullElemCount does not match argc. This program should always return 0.

    A major source of confusion is the fact that argc is not really the count of the arguments your program was invoked with! Yup, there's another extra element in argv; argv[0] is reserved by the standard to hold the name by which the program is invoked. If you compiled prog1 but then renamed it prog2, then argv[0] holds a pointer to the c-string "prog2" (note that on many systems this sting also includes the path from which the program was invoked).

    So =>MyProg Arg1 results in argc being equal to 2. If your program isn't really interested in what it's current filename is, you are free to ignore argv[0]. While all this seems confusing at first, it really turns out to be quite convenient. If your program requires N arguments, you can check argc is N + 1. If it requires < N arguments, you can check argc < N + 1. If your program processes an indeterminate number of arguments, you can walk argv from it's second element (argv[1]) until you encounter a NULL pointer or you can use argc as a count down variable.

    Code:
    int main( int argc, char **argv )
    {
        int MyNonNullElemCount = 0 ;
        int MyArgCount = 0 ;
        char **pArgs = argv ;
    
        printf( "Command line: " ) ;
    
        while ( NULL != *pArgs )
        {
            printf( "%s ", *pArgs ) ;
            if ( MyNonNullElemCount > 0 )
            {
                MyArgCount++ ;
            }
            MyNonNullElemCount++ ;
            pArgs++ ;
        }
    
        printf( "\nargc: %d\nMyNonNullElemCount: %d\nMyArgCount: %d\nReturn: %d\n", argc, MyNonNullElemCount, MyArgCount, MyNonNullElemCount != argc ) ;
    
        return MyNonNullElemCount != argc ;
    }
    If you are new to C; compile and run the above code. Step through it with your debugger. Learn why it works the way it does and you will be well on your way to being a C programmer.

    How/who/what calls main()?

    When you compile and link your program, your code is bound to a set of library functions and c-runtime code that is supplied by the makers of your compiler. The standards require that some things must be initialized before main() is called (which is mostly beyond the scope of this document) and some of those things must be initialized at run-time. Generally, the operating environment loads your program into memory and then jumps to the start address of your program. That start address is NOT main(), it resides in the C/C++ runtime. That code initializes and prepares the environment (including initialization of argv and then calls main(). When your main() function returns, exits or aborts, execution picks up in the run-time code before returning to the operating environment.

    References and Definitions

    [1] Hosted Program
    A program that is hosted by an operating system
    .

    Adenda

    Both standards actually say/imply some things that are not specified above. This was to keep it simple and appropriate for beginners. As with all standards there is always some argument about the interpretation of one thing or another. The above is as portable across compilers as it gets.


    Both standards treat main() as a special function. You can write:

    Code:
    int main( void ) {} /* No return statement! */
    Both standards require that when execution hits the closing brace '}', the main function returns a value of zero. It is considered bad form to rely on this behavior.

    Thanks to Clifford, Salem, Scorpions4ever, sizablegrin for their helpful comments and time spent reviewing this post.

    Please feel free to PM me if you have any comments.

    Comments on this post

    • jafet agrees : Mmm, just in time.
    • RAJ_55555 agrees : I can say that I started learning here, thanks mr. donahue
    Last edited by Scorpions4ever; February 1st, 2010 at 11:28 AM. Reason: New version of this article by jwdonahue.
    I no longer wish to be associated with this site.
  18. #25
  19. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    JW, this is perhaps a quibble, but could you point me to the part of the standard that says a a function named "main" is required?

    I have written a number of embedded programs that didn't require a "main", but that doesn't mean they were compliant.

    I'm just curious, and blind, and I can't find it.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions
  20. #26
  21. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    That isn't a C or C++ standard, that's just the default behaviour of most system libraries they're linked against and/or compilers.

    When gcc creates a binary for example, it assumes main is the entry function and makes it a global in the asm source and tells LD to link assuming that is the main entry point of the binary.

    So, not a part of the c standard, but a voluntary standard that has been adhered to for consistency reasons.
  22. #27
  23. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    San Francisco Bay
    Posts
    1,939
    Rep Power
    1313
    Originally Posted by sizablegrin
    JW, this is perhaps a quibble, but could you point me to the part of the standard that says a a function named "main" is required?

    I have written a number of embedded programs that didn't require a "main", but that doesn't mean they were compliant.

    I'm just curious, and blind, and I can't find it.
    Here, for example. It's on pages 12 & 13 (5.2.2.1 and 5.2.2.3). (It looks like jwdonahue did his homework. :-))
  24. #28
  25. Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jun 2005
    Posts
    5,964
    Rep Power
    4852
    I plead "not guilty" on the grounds that I wrote those programs in the early 80s, before there was a standard.
    Write no code whose complexity leaves you wondering what the hell you did.
    Politically Incorrect DaWei on Pointers Grumpy on Exceptions
  26. #29
  27. fork while true;
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    May 2005
    Location
    England, UK
    Posts
    5,538
    Rep Power
    1051
    However my point (and Wei's) still stands, that it evolved as a result of people using the same name for compatibility. I wasn't aware a standard had been written, but certainly in the c89 standard I'm fairly sure it wasn't a requirement (I have a copy somewhere, I must look that up)

    Feel free to correct me if I'm wrong
    Last edited by LinuxPenguin; September 14th, 2007 at 04:13 AM.
  28. #30
  29. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,155
    Rep Power
    2222
    In Schildt's Annotated ANSI C Standard:

    Section 5.1.2.1, Freestanding environment, states that in a freestanding environment the name and type of the function called at program startup are implementation defined.

    However, Section 5.1.2.2, Hosted environment, states:
    A hosted environment need not be provided, but shall conform to the following specifications if present.
    Section 5.1.2.2.1, Program startup, states in part:
    The function called at program startup is named main. The implementation declares no prototype for this function.
    And the section goes on to discuss different forms that main may take, primarily a void parameter list or a populated list and rules concerning argc and argv.

    In other words, in a freestanding environment anything goes. But a hosted environment must follow a well-defined set of rules, most importantly that C programs begin with the main function. Yes, in a hosted environment it is a requirement.

IMN logo majestic logo threadwatch logo seochat tools logo