return ; what does this statement returns? - c

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

Related

Is `return 0` still important in the `main` function? [duplicate]

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.

What happens when we assign a function call return value with return type void to a int variable?

#include<stdio.h>
int main()
{
//void foo();
int c= 5;
c=foo();
printf("\n%d",c);
return 0;
}
void foo()
{
printf("I am foo");
}
When I am commenting the prototype declaration then it gives the output:
I am foo
8
With prototype it gives the error saying:
void value not ignored as it ought ought to be.
My question is, what is internally happening which result into the output when there is no prototype declaration? What is the reason behind it?
I am using Dev C++ editor with TDM-GCC 4.9.2 64bit compiler.
The sole reason this is built successfully is the implicit int rule (now removed in the latest revision of the C standard).
The compiler sees no forward declaration of foo, so it assumes that its return type is int. It then proceeds to build and call your void foo(). After all is said and done, the behavior of your program is undefined.
Gcc compiler give warning and successfully run and return number of character with whitespace but some compiler give an error.
pp.c:10:6: warning: conflicting types for ‘foo’ [enabled by default]
void foo()
^
pp.c:6:6: note: previous implicit declaration of ‘foo’ was here
c=foo();
when there is no prototype declaration
Well, that is invalid C.
To elaborate,
Point 1: You cannot have a function called which is not declared earlier. It is against the C standard rule.Note
Point 2: As soon as you add the forward declaration, you'll be getting compilation error, as a void type cannot be the RHS operand of an assignment operator and this is a constraint violation for assignment operator.
Note:
Pre C99, it was allowed to have a function being called without the prototype known, it was assumed that the function will be returning an int and will be accepting any number of parameters. However, this is precisely forbidden as per C99 and later, as the "implicit int rule" is removed from the standard. (Refer Foreword, paragraph 5, _"remove implicit int"_ in C99 standard).
In your case, for legacy reasons, the compiler still supports the implicit int rule, so it compiles fine, however, the assumption by compiler and the actual function definition is a mismatch. This invokes undefined behavior.
Quoting C11, chapter §6.5.2.2, Function calls
If the function is defined with a type that is not compatible with the type (of the
expression) pointed to by the expression that denotes the called function, the behavior is
undefined.

Defining a function returning incompatible type, but unreachable

After reading through the C99 standard, I could not find any sections which would forbid defining function f below:
struct s { double d; };
int f() {
if (0) return (struct s){.d = 3.14};
// There is intentionally no return statement of type int, which is valid
}
int main() {
f();
return 0;
}
In particular, this program's behavior should be defined, since the return value is (a) never reached in the first place and (b) never used, even if it were reached.
Still, most of my compilers (GCC, Clang and CompCert) prevent this program from being compiled, with error returning 'struct s' from a function with incompatible result type 'int'. I did manage to compile it with tcc, but I don't know if it's mostly due to luck (i.e. lack of verifications).
Could someone please confirm if this program is syntactically C99 valid, and also that its behavior is completely well-defined, or otherwise indicate where the standard forbids it?
I actually prefer that my compilers reject it, but for instance some macro definitions could produce code similar to this one, so it could be actually useful to accept such programs if they are valid.
Background
Below are the possibly relevant excerpts of the C99 standard that I could find, along with my reasoning on why they should not forbid my program from being syntactically valid and semantically well-defined:
§6.8.6.4 The return statement
§6.8.6.4.1 A return statement with an expression shall not appear in a function whose return type is void. A return statement without an expression shall only appear in a function whose return type is void.
In my code, we have a non-void function with a non-void return, so everything seems fine.
§6.8.6.4.3 If a return statement with an expression is executed, the value of the expression is returned to the caller as the value of the function call expression. If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function.
Because the return statement is never executed, the above does not apply.
§6.9.1 Function definitions
§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.
The result of the function call is not used by the caller, so the behavior should be defined.
"If the expression has a type different from the return type of the function in which it appears, the value is converted as if by assignment to an object having the return type of the function." is a standalone sentence. It is not conditional on "If a return statement with an expression is executed" so applies even to your code. And I'm pretty sure you already know that conversion as if by assignment means that incompatible types allow for a compile-time error.

function doesn't display the return value?

Why it doesn't return any value?
The output should be 155 but it always display 0. why?
int main()
{
int i=5;
printf("%d",fun(fun(fun(fun( fun(i))))));
return 0;
}
void fun(int i)
{
if(i%2) return (i+(7*4)-(5/2)+(2*2));
else return (i+(17/5)-(34/15)+(5/2));
}
But if I change
void fun(int i) // It doesn't work, case 1
to
int fun(int i) //It works fine, case 2
If fun doesn't return any value in case 1 ( void fun(int i) ), then how come
fun(fun(fun(fun( fun(i)))))); this statement is working?
Case 1 is undefined behavior, if we look at the C99 draft standard section 6.8.6.4 The return statement says(emphasis mine):
A return statement with an expression shall not appear in a function whose return type
is void. A return statement without an expression shall only appear in a function
whose return type is void
but if you do not have a declaration then most likely the compiler is implying the return type as int but then there is a mismatch between the declaration and implementation, this as far as I can tell then become undefined behavior again. I am able to run this on the latest gcc with the same result but I do receive the following warnings:
warning: implicit declaration of function 'fun' [-Wimplicit-function-declaration]
warning: conflicting types for 'fun' [enabled by default]
You have no declaration for your fun function at the time it is called so the compiler implicitly put a declaration with int return value.
In C89 if there is no visible declaration, it is as if the declaration:
extern int fun();
appeared before the function call. But as your function definition actually has void return value, your program invokes undefined behavior.
In C99, the rule for implicit function declaration has been removed and a diagnostic has to be issued.
EDIT: Actually as stated by #Shafik Yaghmour you are also having a return statement in a void function. This is a constraint violation in C89 (and C99 / C11) and the compiler has the right to stop the translation.
Both answers provided so far (by Shafik and ouah) are correct and complementary (and +1). But I want to stress something once more: do not ignore the warnings that a compiler gives you. Warnings in C can often save you from a lot of trouble.
When you compile your code (e.g. in gcc), you will see:
warning: ‘return’ with a value, in function returning void
This plainly says that you have a function that shouldn't return anything and, still, you're trying to return an integer from it. As the result type is explicitly declared to be void, the compiler chooses simply to ignore whatever you return; this appears as if you always return zero. This may seem strange but, as what you're doing is undefined behavior, the compiler is entitled to do so.

Why is return 0 optional?

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.

Resources