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.
Related
I tried this program on DevC++ that would call two different types of function, one returning int and one returning char. I'm confused why the int function doesn't need a prototype, while the char one and any other type of function does.
#include <stdio.h>
//int function1();
char function2() ;
int main (){
int X = function1() ;
char Y = function2() ;
printf("%d", X) ;
printf ("%c", Y) ;
return 0 ;
}
int function1(){
return 100 ;
}
char function2(){
return 'B' ;
}
The output:
100B
If I remove the prototype for the char function, it results in:
[Error] conflicting types for 'function2'
[Note] previous implicit declaration of 'function2' was here
In the old days of C any function that was not declared explicitely was supposed to return int type when you call it.
If the compiler then finds the function implementation and sees an int return type, everything is fine.
If the function returns anything else than int you get the error message as you saw with the second function.
This implicit int type declaration was removed from the standard with C99. Now you should at least get a warning from your compiler when you use a function without prototype.
If you did not get any diagnostic message for first funcion, you should turn up warning level in your compiler or switch to at least C99 mode instead of ancient versions.
Edit:
Empty parameter lists in funcion definitions is a deprecated feature as well.
You should not use it.
Always provide prototype for every function with return type and parameter list.
If a function is used before it is declared, the usage becomes an implicit declaration of the function. When a function f is implicitly defined, the definition given to it is int f(), i.e. a function which accepts an unspecified number of arguments and returns an int.
This implicit definition of a function matches the actual definition of function1 but not function2. So calling function1 this way gives no error but attempting to call function2 this way results in the implicit definition not matching the actual definition, giving an error.
This behavior goes back to pre-standardized versions of C where all objects (and a function's return type) had a default type of int if not declared. This was still present in the C89 standard but removed in the C99 standard, although some compilers such as gcc still support this obsolescent usage as an extension.
It's just an ancient relic from when C was first designed. It was actually removed as early as C99, but many compilers still support this type of declaration. But it's not recommended to use it.
I'm not sure if there were any real rationale behind it, but C was heavily inspired by the language B. And in B you did not have to specify the return type for functions. That actually made perfect sense, because there was only one type, word.
In the same way you did not have to specify the type of variables either. You only specified if it had automatic or static storage. And that's where the completely useless keyword auto in C comes from. It does not mean the same as in C++. It just means "not static".
I have code:
#include <stdio.h>
int main() {
int a = sum(1, 3);
return 0;
}
int sum(int a, int b, int c) {
printf("%d\n", c);
return a + b + c;
}
I know that I have to declare functions first, and only after that I can call them, but I want to understand what happends.
(Compiled by gcc v6.3.0)
I ignored implicit declaration of function warning and ran program several times, output was this:
1839551928
-2135227064
41523672
// And more strange numbers
I have 2 questions:
1) What do these numbers mean?
2) How function main knows how to call function sum without it declaration?
I'll assume that the code in your question is the code you're actually compiling and running:
int main() {
int a = sum(1, 3);
return 0;
}
int sum(int a, int b, int c) {
printf("%d\n", c);
return a + b + c;
}
The call to printf is invalid, since you don't have the required #include <stdio.h>. But that's not what you're asking about, so we'll ignore it. The question was edited to add the include directive.
In standard C, since the 1999 standard, calling a function (sum in this case) with no visible declaration is a constraint violation. That means that a diagnostic is required (but a conforming compiler can still successfully compile the program if it chooses to). Along with syntax errors, constraint violations are the closest C comes to saying that something is illegal. (Except for #error directives, which must cause a translation unit to be rejected.)
Prior to C99, C had an "implicit int" rule, which meant that if you call a function with no visible declaration an implicit declaration would be created. That declaration would be for a function with a return type of int, and with parameters of the (promoted) types of the arguments you passed. Your call sum(1, 3) would create an implicit declaration int sum(int, int), and generate a call as if the function were defined that way.
Since it isn't defined that way, the behavior is undefined. (Most likely the value of one of the parameters, perhaps the third, will be taken from some arbitrary register or memory location, but the standard says nothing about what the call will actually do.)
C99 (the 1999 edition of the ISO C standard) dropped the implicit int rule. If you compile your code with a conforming C99 or later compiler, the compiler is required to diagnose an error for the sum(1, 3) call. Many compilers, for backward compatibility with old code, will print a non-fatal warning and generate code that assumes the definition matches the implicit declaration. And many compilers are non-conforming by default, and might not even issue a warning. (BTW, if your compiler did print an error or warning message, it is tremendously helpful if you include it in your question.)
Your program is buggy. A conforming C compiler must at least warn you about it, and possibly reject it. If you run it in spite of the warning, the behavior is undefined.
This is undefined behavior per 6.5.2.2 Function calls, paragraph 9 of the C standard:
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.
Functions without prototypes are allowed under 6.5.2.2 Function calls, paragraph 6:
If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. ...
Note again: if the parameters passed don't match the arguments expected, the behavior is undefined.
In strictly standard conforming C, if you don't declare a function before using it, it will assume certain default argument types for the function.This is based on early versions of C with a weaker type system, and retained only for backwards compatibility. It should not be used generally.
Ill skip the details here, but in your case it assumes sum takes 2 ints and returns an int.
Calling a function with the wrong number of parameters, as you are doing here, is undefined behaviour. When you call sum, the compiler thinks that it takes two integers, so it passes two integers to it. When the function is actually called, however, it tries to read one more integer, c. Since you only passed 2 ints, the space for c contains random crap, which is what you're seeing when you print out. Note that it doesn't have to do this, since this is undefined behaviour, it could do anything. It could have given values for b & c, for example.
Obviously this behaviour is confusing, and you should not rely on undefined behaviour, so you'd be better off compiling with stricter compiler settings so this program wouldn't compile. (The proper version would declare sum above main.)
1) Since you haven't provided value for parameter "c" when calling function "sum" its value inside the function is undefined. If you declared function before main, your program wouldn't even compile, and you would get "error: too few arguments to function call" error.
2) Normally, it doesn't. Function has to be declared before the call so the compiler can check function signature. Compiler optimizations solved this for you in this case.
I'm not 100% sure if C works exactly like this but, your function calls work like a stack in memory. When you call a function your arguments are put on that stack so when in the fuction you can access them by selecting less x positions on memory. So:
You call summ(1, 3)
the stack will have 1 and the on the top a 3.
when executing the fuction it will see the last position of memory for the 1º argument (it recovers the 1) and then the position before that for the 2º argument (recovering the 3), however, there is a 3º argument so it accesses the position before that as well.
This position is garbige as not put by you and different everytime you run it.
Hope it was clear enought. Remeber that the stack works is inverted so every time you add something it goes to the previous memory position, not the next.
I know I shouldn't define any function like that. But I like to try the limits, so I wrote some code like that:
#include <stdio.h>
void func(a)
{
printf("%d\n", a);
}
int main()
{
func();
func();
func();
return 0;
}
I really wasn't looking for any outputs, but the one I saw was very odd.
The output is
1
0
0
Why? Where did those 1's or 0's came from?
(I'm using CygWin & Eclipse duo btw.)
Your program is invalid.
gcc 8.2 complains:
$ gcc -Wall -Wextra -pedantic -std=c17 t.c
test.c: In function ‘func’:
test.c:3:6: warning: type of ‘a’ defaults to ‘int’ [-Wimplicit-int]
void func(a)
Since C99, all functions require their arguments to have valid types (there used to be "implicit int" rule - function argument/return types are assumed int if not specified). But your program is not valid in C89 either because you don't actually pass any argument. So what you see is the result of undefined behaviour.
Prior to the 1989 ANSI C standard, the only way to define a function in C did not specify the number and types of any parameters. (This old version of the language is called "K&R C", since it's described in the first edition of The C Programming Language by Kernighan and Ritchie.) You're using an old-style function definition:
void func(a)
{
printf("%d\n", a);
}
Here a is the name of the parameter. It is implicitly of type int, but that information is not used in determining the correctness of a call to func.
C89 added prototypes, which allow you to specify the types of parameters in a way that is checked when the compiler sees a call to the function:
void func(int a)
{
printf("%d\n", a);
}
So in the 1989 version of the C language, your program is legal (in the sense that there are no errors that need to be diagnosed at compile time), but its behavior is undefined. func will probably grab whatever value happens to be in the location in which it expects the caller to place the value of the argument. Since no argument was passed, that value will be garbage. But the program could in principle do literally anything.
The 1999 version of the language dropped the "implicit int" rule, so a is no longer assumed to be of type int even with the old-style definition.
But even the latest 2011 version of C hasn't dropped old-style function definitions and declarations. But they've been officially obsolescent since 1989.
Bottom line: Always use prototypes. Old-style function definitions and declarations are still legal, but there is never (or very rarely) any good reason to use them. Unfortunately your compiler won't necessarily warn you if you use them accidentally.
(You're also using an old-style definition for main. int main() is better written as int main(void). This is less problematic than it is for other functions, since main is not normally called, but it's still a good habit.)
When you don't define type for the variables int is taken as default type by compiler.
warning: type of 'a' defaults to 'int' [-Wimplicit-int]
void func(a)
Hence it is printing indeterminate values which int a contains.
#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.
This question already has answers here:
Are prototypes required for all functions in C89, C90 or C99?
(6 answers)
Closed 8 years ago.
I am kind of new to C (I have prior Java, C#, and some C++ experience). In C, is it necessary to declare a function prototype or can the code compile without it? Is it good programming practice to do so? Or does it just depend on the compiler? (I am running Ubuntu 9.10 and using the GNU C Compiler, or gcc, under the Code::Blocks IDE)
It is never required to declare a prototype for a function in C, neither in "old" C (including C89/90) nor in new C (C99). However, there's a significant difference between C89/90 and C99 with regard to function declarations.
In C89/90 it was not necessary to declare a function at all. If the function is not declared at the point of the call, the compiler "guesses" (infers) the declaration implicitly from the types of the arguments passed in the call and assumes that the return type is int.
For example
int main() {
int i = foo(5);
/* No declaration for `foo`, no prototype for `foo`.
Will work in C89/90. Assumes `int foo(int)` */
return 0;
}
int foo(int i) {
return i;
}
In C99 every function that you call must be declared before point of the call. However, it is still not necessary to declare it with a prototype specifically. A non-prototype declaration will work as well. This means that in C99 the "implicit int" rule no longer works (for inferred function return types, in this case), but parameter types can still be guessed from the argument types if function is declared without a prototype.
The previous example will not compile in C99, since foo is not declared at the point of the call. Yet, you can add a non-prototype declaration
int foo(); /* Declares `foo`, but still no prototype */
int main() {
int i = foo(5);
/* No prototype for `foo`, although return type is known.
Will work in C99. Assumes `int foo(int)` */
return 0;
}
...
and end up with valid C99 code.
Nevertheless, it is always a good practice to declare a prototype for the function before you call it.
An additional note: I said above that it is never required to declare a function prototype. In fact, for some functions it is a requirement. In order to properly call a variadic function in C (printf for example) the function must be declared with a prototype before the point of the call. Otherwise, the behavior is undefined. This applies to both C89/90 and C99.
In ANSI C (meaning C89 or C90), you do not have to declare a function prototype; however, it is a best practice to use them. The only reason the standard allows you to not use them is for backward compatibility with very old code.
If you do not have a prototype, and you call a function, the compiler will infer a prototype from the parameters you pass to the function. If you declare the function later in the same compilation unit, you'll get a compile error if the function's signature is different from what the compiler guessed.
Worse, if the function is in another compilation unit, there's no way to get a compilation error, since without a a prototype there's no way to check. In that case, if the compiler gets it wrong, you could get undefined behavior if the function call pushes different types on the stack than the function expects.
Convention is to always declare a prototype in a header file that has the same name as the source file containing the function.
In C99 or C11, standard C requires a function declaration in scope before you call any function. Many compilers do not enforce this restriction in practice unless you force them to do so.
it's not a must, if the function is defined before its use.
It is not required, but it is bad practice not to use prototypes.
With prototypes, the compiler can verify you are calling the function correctly (using the right number and type of parameters).
Without prototypes, it's possible to have this:
// file1.c
void doit(double d)
{
....
}
int sum(int a, int b, int c)
{
return a + b + c;
}
and this:
// file2.c
// In C, this is just a declaration and not a prototype
void doit();
int sum();
int main(int argc, char *argv[])
{
char idea[] = "use prototypes!";
// without the prototype, the compiler will pass a char *
// to a function that expects a double
doit(idea);
// and here without a prototype the compiler allows you to
// call a function that is expecting three argument with just
// one argument (in the calling function, args b and c will be
// random junk)
return sum(argc);
}
In C, if we do not declare a function prototype and use the function definition, there is no problem and the program compiles and generates the output if the return type of the function is "integer". In all other conditions the compiler error appears. The reason is, if we call a function and do not declare a function prototype then the compiler generates a prototype which returns an integer and it searches for the similar function definition. if the function prototype matches then it compiles successfully. If the return type is not integer then the function prototypes do not match and it generates an error. So it is better to declare function prototype in the header files.
C allows functions to be called even though they have not previously been declared, but I strongly recommend you to declare a prototype for all functions before using them so that the compiler can save you if you use the wrong arguments.
You should put function declarations in the header file (X.h) and the definition in the source file (X.c). Then other files can #include "X.h" and call the function.
Function prototype is not mandatory according to the C99 standard.
It's not absolutely necessary to declare a function for the calling code to compile. There are caveats though. Undeclared function is assumed to return int and compiler will issue warnings first about function being undeclared and then about any mismatches in return type and parameter types.
Having said that it's obvious that declaring functions properly with prototypes is a much better practice.
Select ‘Options’ menu and then select ‘Compiler | C++
Options’. In the dialog box that pops up, select ‘CPP always’
in the ‘Use C++ Compiler’ options.
Again select ‘Options’ menu and then select ‘Environment |
Editor’. Make sure that the default extension is ‘C’ rather than
‘CPP’.