Why, if I write
int main()
{
//...
}
do I not need to write return 0; at the end of the main function? Does the compiler do it for me?
I use GCC / C99.
C99 and C++ special case the main function to return 0 if control reaches the end without an explicit return. This only applies to the main function.
The relevant bit of the C99 spec is 5.1.2.2.3 for the main special case
5.1.2.2.3 Program termination
If the return type of the main function
is a type compatible with int, a
return from the initial call to the
main function is equivalent to calling
the exit function with the value
returned by the main function as its
argument; reaching the } that
terminates the main function returns
a value of 0.
6.9.1/12
If the } that terminates a function is
reached, and the value of the function
call is used by the caller, the
behavior is undefined.
You can test this out with gcc:
int foo ( void ) { }
int main( void ) { }
C89 mode ( errors for both functions ):
sandiego:$ gcc src/no_return.c -std=c89 -Wall
src/no_return.c: In function ‘main’:
src/no_return.c:2: warning: control reaches end of non-void function
src/no_return.c: In function ‘foo’:
src/no_return.c:1: warning: control reaches end of non-void function
C99 mode ( main is a special case ) :
sandiego:$ gcc src/no_return.c -std=c99 -Wall
src/no_return.c: In function ‘foo’:
src/no_return.c:1: warning: control reaches end of non-void function
The most recent C (currently that's C99 with a few amendments) returns 0 from main by default if there is no explicit return statement at the end of the function, and control flows off the function's end (see 5.1.2.2.3 in C99 TC3). This is because most often one would write such a form of return anyway.
In C89 you need to return something there - it has no such implicit return. But the compiler is by no means required to diagnose such a mistake (see 3.6.6.4 in the C89 draft and 6.9.1/12 in C99 TC3).
Yes. main in C is a very special function that has some extra rules. See the paragraph in the C99 standard about its termination below. In essence it says that if you quit the function without returning a value this is equivalent as if you had given a return value of 0. This is special to main, doing so with other functions where the calling function expects a return value might (and will) crash your program.
If the return type of the main
function is a type compatible with
int, a return from the initial call to
the main function is equivalent to
calling the exit function with the
value returned by the main function as
its argument; reaching the } that
terminates the main function returns a
value of 0. If the return type is not
compatible with int, the termination
status returned to the host
environment is unspecified.
Basically, yes. Functions are not required to return anything, even if they declare a return type other than void. The value returned will be undefined.
Note that C99 requires that functions that declare non-void return types always terminate by hitting a return statement. So if you were compiling using your compiler's C99 mode this code would result in a compile-time error.
Related
Why, if I write
int main()
{
//...
}
do I not need to write return 0; at the end of the main function? Does the compiler do it for me?
I use GCC / C99.
C99 and C++ special case the main function to return 0 if control reaches the end without an explicit return. This only applies to the main function.
The relevant bit of the C99 spec is 5.1.2.2.3 for the main special case
5.1.2.2.3 Program termination
If the return type of the main function
is a type compatible with int, a
return from the initial call to the
main function is equivalent to calling
the exit function with the value
returned by the main function as its
argument; reaching the } that
terminates the main function returns
a value of 0.
6.9.1/12
If the } that terminates a function is
reached, and the value of the function
call is used by the caller, the
behavior is undefined.
You can test this out with gcc:
int foo ( void ) { }
int main( void ) { }
C89 mode ( errors for both functions ):
sandiego:$ gcc src/no_return.c -std=c89 -Wall
src/no_return.c: In function ‘main’:
src/no_return.c:2: warning: control reaches end of non-void function
src/no_return.c: In function ‘foo’:
src/no_return.c:1: warning: control reaches end of non-void function
C99 mode ( main is a special case ) :
sandiego:$ gcc src/no_return.c -std=c99 -Wall
src/no_return.c: In function ‘foo’:
src/no_return.c:1: warning: control reaches end of non-void function
The most recent C (currently that's C99 with a few amendments) returns 0 from main by default if there is no explicit return statement at the end of the function, and control flows off the function's end (see 5.1.2.2.3 in C99 TC3). This is because most often one would write such a form of return anyway.
In C89 you need to return something there - it has no such implicit return. But the compiler is by no means required to diagnose such a mistake (see 3.6.6.4 in the C89 draft and 6.9.1/12 in C99 TC3).
Yes. main in C is a very special function that has some extra rules. See the paragraph in the C99 standard about its termination below. In essence it says that if you quit the function without returning a value this is equivalent as if you had given a return value of 0. This is special to main, doing so with other functions where the calling function expects a return value might (and will) crash your program.
If the return type of the main
function is a type compatible with
int, a return from the initial call to
the main function is equivalent to
calling the exit function with the
value returned by the main function as
its argument; reaching the } that
terminates the main function returns a
value of 0. If the return type is not
compatible with int, the termination
status returned to the host
environment is unspecified.
Basically, yes. Functions are not required to return anything, even if they declare a return type other than void. The value returned will be undefined.
Note that C99 requires that functions that declare non-void return types always terminate by hitting a return statement. So if you were compiling using your compiler's C99 mode this code would result in a compile-time error.
Suppose I have the following function definition:
int foo () {
int x;
x = x + 2;
}
As you can see, this function is declared to return an int value, but there is no return statement, and it also does not get any parameters.
Given this function as defined above, what type of error does it constitute - syntactic ? semantic ? run-time ? not type of any error ?
This is not considered a bad syntax. It is ok in accordance with the 'c' standard. Therefore it would compile ok, but the results will be unpredictable.
As mentioned in comments, it is just bad programming. Modern compilers can detect such common issues with the programs. So, with gcc -Wall you can get the following diagnostics for missing return statement (control reaches ...) and uninitialized variable.
%> gcc a.c -Wall
a.c: In function 'foo':
a.c:1:1: warning: control reaches end of non-void function [-Wreturn-type]
int foo () { int x; x=x+2;}
^~~
a.c:1:22: warning: 'x' is used uninitialized in this function [-Wuninitialized]
int foo () { int x; x=x+2;}
~^~~~
a.c:1:18: note: 'x' was declared here
int foo () { int x; x=x+2;}
Neither. It is valid C but undefined behavior if the returned value is used by the caller. The C standard 6.9.1/12 (semantics) says:
If the } that terminates a function is reached, and the value of the function call is used by
the caller, the behavior is undefined.
When the meaning of a program is not what was intended, it is a semantic error.
First, let us correct the function so it initializes x:
int foo(void)
{
int x = 0;
x = x + 2;
}
Second, let us suppose the return value of the function is used somewhere. Then C 6.9.1 12 tells us:
Unless otherwise specified, if the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
If we further presume that the author did not intend to write a program with undefined behavior and that nothing else, such as the compiler implementation, defines the behavior, then the meaning of the program foo is not what the author intended—they intended it to execute with some defined behavior, but it does not, and therefore there is an error. It is an error in what the source code of the program means, and that is a semantic error.
#include <stdio.h>
int main(void)
{
printf("Hello, World\n");
}
In the code above (originally shown as a picture), the return type for the main function is int but we are not returning any value in that function.
This function works even without the return statement.
How is that possible?
As of C99, it's well-defined.
§ 5.1.2.2.3 Program termination
reaching the } that terminates the main function returns a value of 0.
In C99 and C11 §5.1.2.2.3 Program termination, the standard stipulates:
5.1.2.2.3 Program termination
¶1 If the return type of the main function is a type compatible with int, a return from the
initial call to the main function is equivalent to calling the exit function with the value
returned by the main function as its argument;11) reaching the } that terminates the
main function returns a value of 0. If the return type is not compatible with int, the
termination status returned to the host environment is unspecified.
11) In accordance with 6.2.4, the lifetimes of objects with automatic storage duration declared in main
will have ended in the former case, even where they would not have in the latter.
There was no similar provision in C90. If you return from main() in a C90 program by falling off the end (rather than by executing a return with a value), the value returned to the environment is undefined. The code still worked, but programs such as the shell could not reliably detect whether the program was successful or not.
ISO/IEC 9899:1990
5.1.2.2.3 Program termination
¶1 A return from the initial call to the main function is equivalent to calling the exit function
with the value returned by the main function as its argument. If the main function executes a return that specifies no value, the termination status returned to the host environment is undefined.
6.6.6.4 The return statement
¶3 If a return statement without an expression is executed, and the value of the function call is used by the caller, the behavior is undefined. Reaching the } that terminates a function is equivalent to executing a return statement without an expression.
This paragraph is not present in C11 §6.8.6.4 The return statement.
Thus, if your compiler supports C99 or C11, dropping off the end of main() is equivalent to return 0; but this was not the case before C99. I believe this was done as much for conformity with C++98 (which has essentially the same rule) as for any other reason.
Speaking personally, I dislike the rule and my main() programs normally end return 0;.
This is to keep the code compatible with earlier stages of C.
C compiler implicitly does it for you. :)
i.e
return 0;
I have some legacy C code that I compiled with gcc version 4.9.2 on Linux with return-type warning on [-Wreturn-type]. I have a function as below:
int somefn() {
// .. do something ..
// no explicit return statement
}
and the caller had the call as below:
if (somefn()){
// handling of success
}
else {
// handling of failure
}
When warnings were suppressed, compilation+linking went all ok, and at runtime, we may get surprises, What could go wrong?
Quoting C11, chapter §6.9.1, Function Definitions, Semantics
If the } that terminates a function is reached, and the value of the function call is used by
the caller, the behavior is undefined.
So, the standard specifies the semantics of the function definition and it clearly states that (for a non-void function return type) a function which terminates without a return statement and the returned value is used in caller causes undefined behavior.
So, it accepts that syntactically writing a function as such will be possible, but attempt to make use of that will be UB. It does not state this as a constraint violation and I see no reason for a conforming compiler to produce an "error".
In case you want strict check (which is recommended, by the way), use -Werror option.
I compiled with gcc version 4.9.2 on Linux with return-type warning on [-Wreturn-type]
The caller expected a true (in C, interpreted as non-zero) for success and 0 for failure. This is what was happening. Since a function that returns non-void, when called, space is created on the stack for the return value, then context is switched to the callee, and finally, when the control comes back to the caller, context is switched back popping all local variables from stack and keeping the return value there on stack to be popped by the caller after return from callee. Thus, having no explicit return statement caused some value to be returned. That is equivalent to having explicit return statement as ‘return 1;’ or 'return 0;' as appropriate. So, better (of course) would be to have explicit return statement e.g.
int somefn() {
// .. do something ..
if (..somecond..)
return 0; // failure
else
return 1; // success
}
To avoid surprises, I would say, compilers should flag 'no return statement in function returning non-void' as error.
consider following code:
#include <stdio.h>
int main( )
{
int a ;
a = message( ) ;
printf("--%d",a);
}
message( )
{
printf("--%d",printf ( "\nViruses are written in C" ));
return ;
}
I am getting output as:(in GCC)
Viruses are written in c--25--4
My explanation: return ; statement returns the value in the Accumulator,the value returned by the latest printf is stored in the accumulator...
is this correct or not?
The behaviour is undefined.
The reason you're seeing the 4 is that your code happened not to overwrite the register used to return values from functions (eg. eax on 32-bit Intel) between the printf that prints --%d in message (which printed the four characters --25) and the final printf in main.
You are invoking undefined behavior by returning nothing from a value returning function though. If we look at the draft C99 standard section 6.8.6.4 The return statement says:
[...] A return statement without an expression shall only appear in a function
whose return type is void.
You should really have no expectations on how this should run but you can make some good guesses as Deep C presentation demonstrates in several sections but I would never do any of this in a production environment.
If you had warnings enabled you should have seen several informative messages, for example gcc provides the following warnings:
warning: implicit declaration of function ‘message’ [-Wimplicit-function-declaration]
warning: return type defaults to ‘int’ [enabled by default]
warning: ‘return’ with no value, in function returning non-void [enabled by default]
You are also relying on implicit return types are no longer allowed since C99 but compilers like gcc do support them even in C99 mode. So if that is the case then message will have an int implicit return type.
It returns nothing. It will terminate your function only. But as your function has no return type in C89 its return type implicitly converted to int, but it is not legal in C99 and latter and this will invoke undefined behavior.
If a non-void function reaches the end of its body--that is, it fails to execute a return statement--the behavior of the program is undefined if it attempts to use value returned by the function.
Some compilers will issue a warning:
control reaches end of non-void function