Reputation: 273
As far as I know, return
statement in void function will throw an error.
But in the below program that is not the case.
Here the displayed output is 1
. How comes?
main()
{
int i=5;
printf("%d",fun(fun(fun(i))));
}
void fun(int i)
{
if (i%2)
{
return (i+(7*4)-(5/2)+(2*2));
}
else
{
return (i+(17/5)-(34/15)+(5/2));
}
}
Upvotes: 5
Views: 3229
Reputation: 20720
Because C is compiled to binary, technically, functions always return a value. With most modern processors, the returned value is saved in a register¹, such as RAX
(or EAX
in 32 bit) on an Intel processor, and you just can't remove a register from your CPU.
When you create a void function, the compiler will ignore the result, but it is still there.
In your case, the fun(fun(fun(i)))
² expression will pass i
to the first call, then, on an Intel processor on Linux, it will do MOV RDI, RAX
for the second and third calls. These simply copy the result in RAX
to the first parameter of the fun()
function which in assembly is RDI
.
So this is why your code does something. However, today it is considered Undefined Behavior. In the old days, when you could make your software work, it was considered a success. Any code that compiled was considered valid code...
¹ On some processors, especially some old 8 bit CPUs, a specific memory location may be used or the caller had to pass an address where the return value had to be written.
² Assuming your C compiler accepts such, which it shouldn't. At least gcc 11.3 refused to compile that code.
Upvotes: -2
Reputation: 263237
A return
statement with no expression:
void func(void) {
return;
}
is perfectly legal in a void
function. The legality of a return
statement with an expression depends on the version of the C language you're using.
The 1990 C standard says:
A
return
statement with an expression shall not appear in a function whose return type isvoid
.
The 1999 and 2011 editions of the standard both say:
A
return
statement with an expression shall not appear in a function whose return type isvoid
. Areturn
statement without an expression shall only appear in a function whose return type isvoid
.
This is a constraint, meaning that a compiler must issue a diagnostic (possibly a non-fatal warning) for any program that violates it.
C90 permitted a return
statement with no expression in a non-void
function for historical reasons. Pre-ANSI C did not have the void
keyword, so there was no way to define a function that didn't return a value. Programmers would omit the return type (which would default to int
) and simply ignore it. The C90 rule allowed such old code to compile without error. You could still fail to return a value from a non-void
function; the program's behavior is undefined if a caller attempts to use the (nonexistent) result. The 1999 standard tightened up the rules a bit.
Another problem with your program is that you call fun
before its declaration is visible. Under C99 and later rules, this is illegal (though a compiler might merely warn about it). Under C90 rules, this is legal, but the compiler will assume that the function returns int
. Your program's behavior is undefined, but your void
function fun
might happen to behave as if it returned a value, and a call to it might happen to behave as if it used that value.
C compilers tend to be fairly lax about some errors, so that old code (sometimes written before the first actual standard was published) will not be rejected. But your compiler should have at least warned you about the return
statement, and probably about the invalid call. You should pay close attention to compiler warnings; they should be treated almost the same way as fatal errors. And you should use options to increase the number of things your compiler warns you about. If you're using gcc, use -std=c90
, -std=c99
, or -std=c11
, along with -pedantic
to enforce standard conformance. You can add -Wall
-Wextra` to enable more warnings.
Upvotes: 7
Reputation: 81926
The code you've presented is actually invalid in C99 for a variety of reasons, but the most painful one is below:
foo.c:5:17: warning: implicit declaration of function 'fun' is invalid in C99 [-Wimplicit-function-declaration]
printf("%d",fun(fun(fun(i))));
^
foo.c:8:6: error: conflicting types for 'fun'
void fun(int i)
^
foo.c:5:17: note: previous implicit declaration is here
printf("%d",fun(fun(fun(i))));
^
Note that if you gave a function prototype for fun()
, which you really should, then you would get a different set of errors:
foo.c:7:25: error: passing 'void' to parameter of incompatible type 'int'
printf("%d",fun(fun(fun(i))));
^~~~~~
Upvotes: 4