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.
Related
what is the output of this code?
#include<stdio.h>
//int a;
int main()
{
int a=2;
printf("%d",f1());
}
void f1()
{
int b;
++b;
}
I haven't specified the prototype for f1(), even though its printing
output as 0, could some one explain this?
And the same output is printing even though function's return type is
int
It is called Implicit Function Declaration and it's obsolete. Because there is no declaration for f1() the compiler implicitly declares it. In the implicit declaration the function returns int, so that's why it's behaving as it is however,
It's undefined behavior because f1() does not return an int.
It's an obsolete "feature" and the compiler should be telling you through a warning.
In the 1989 C standard (and earlier pre-standard version of C), a function was implicitly declared by any attempt to call it. The implicit declaration was of the function accepting a variable list of arguments, and returning int.
So, since your printf() statement calls f1() without a preceding declaration of f1(), the compiler assumes it is a function that returns int (and can accept any number of arguments). The behaviour is then undefined, since the function is subsequently defined to return void (i.e. it is not consistent with the implicit declaration).
Under C99 and later, this will normally result in a compilation error. Most C89 compilers accept implicit declarations silently by default, but can be configured (higher warning levels) to give a warning. Some compilers from some vendors (notably gcc) continue to support the implicit declaration even when compiling for later C standards, and are still configured by default to not give a warning.
Note 1: if your compiler accepts an implicit declaration of f1(), it will probably also compile without the #include <stdio.h> - since printf() will also be implicitly declared.
Note 2: Your definition of f1() also has undefined behaviour, since b is uninitialised and of automatic storage duration. Accessing its value, let alone incrementing it, therefore gives undefined behaviour.
#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.
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.
#include <stdio.h>
void main()
{
int k = m();
printf("%d", k);
}
void m()
{
printf("hello");
}
Output
hello5
What is the void function returning here?
If there is no printf() then the output is 1.
What is happening here?
A void function does not return anything. Your program invokes undefined behavior because it implicitly defines m to have return type int (in C89, if a function is called before it is declared, it's implicitly assumed to have return type int), but then defines it with return type void.
If you add a forward-declaration for m, the compiler will correctly complain that you're trying to use the return value of a void function, which is not possible.
In both cases (void m with caller expecting int, void main with caller-in-C-library expecting int), this is undefined behavior, and your compiler should have chewed you out, e.g. [GCC 4.8 with -Wall]:
test.c:3:6: warning: return type of ‘main’ is not ‘int’
void main()
^
test.c: In function ‘main’:
test.c:7:5: warning: implicit declaration of function ‘m’
int k = m();
^
test.c: At top level:
test.c:13:6: warning: conflicting types for ‘m’
void m()
^
test.c:7:13: note: previous implicit declaration of ‘m’ was here
int k = m();
^
"Implicit declarations" exist only for backward compatibility with pre-C1989 programs, which are more than 20 years out of date at this point. If you had written this code in a more modern style you would've gotten a hard error:
#include <stdio.h>
extern void m(void);
int main(void)
{
int k = m();
printf("%d", k);
return 0;
}
void m(void)
{
printf("hello");
}
⇒
test.c: In function ‘main’:
test.c:7:13: error: void value not ignored as it ought to be
int k = m();
^
The key addition is the extern void m(void); line. The compiler isn't allowed to look ahead to the definition of m when it checks main for errors, so you need a forward declaration to tell it what m's type really is. You should also know that in C (but not C++), void m() means "m takes an unspecified number of arguments". To declare a function taking no arguments, which is what you wanted, you have to write void m(void).
I believe what is happening on your specific system is that the return value of printf, which your code officially ignores, is being left in the return-value register and thus interpreted as the return value of m, but you cannot rely on anything predictable happening. That is what 'undefined behavior' means.
This is undefined behavior.
The reason the compiler lets you do the assignment is that there is no prototype of m available to it. When this happens, C standard says that the function must return int. Since in this case the actual function return type is void, the behavior is undefined. The value that you get in variable k is entirely arbitrary.
The return value of a function usually stored in the one of the CPU registers, EAX for x86. As C it just a friendly assembler, you can always read the value from the register. And you will get whatever was there. Efficiently, int k = m() tells program to store value of register EAX in the variable k.
You have not declared void m(); before calling it in main.
Some compilers assume the return type of unknown function symbols as int (unknown at the time of compilation of course) . In fact, your compiler has probably issued a compilation warning on this.
If you declare this function before main (where it should be declared), then you will probably get a compilation 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