C function definition and declaration - c

I'm a Java programmer,I learnt a little C++ and now I'm studying a little C for my job.
I can't understand C behaviour about function declaration/definition and related function calls.
From K&R I know that in C (very different from C++) I can call a function that has not been previously declared,and the compiler assumes an implicit declaration of the type:
int main()
{
function(10); // implicit function declaration ( int function() )
}
and I know that such a declaration implies a function that accepts a fixed but indefinite number of arguments of any type (as long as each call is consistent with the others). And I know this is K&R C, before C89, but I want to know how it works as well.
Now, I have this test code, I can't understand:
#include <stdio.h>
function();
int main()
{
printf("hello %d",function(1,2,3));
implicit(11,12,32); // implicit function declaration ( implicit() )
}
int implicit(int b)
{
}
function(int a)
{
}
in the case of function the declaration (return type is assumed to be int,no assumption about the arguments) does match the definition (the compiler issues a warning) but if I call the function with the wrong arguments,it compiles!
Same for the function implicit.
I can't understand..

The thing you have to remember is that the compile is pretty much sequential when it comes to declarations and definition. When the compiler processes the call for function all it has is the declaration that, as you say, doesn't have any assumptions about the arguments, which means you can call the function with any argument you like. When the compiler sees the definition, it doesn't go back to issue an error about the call, it might issue a warning though.
As for the implicit function, when the compiler first sees it it will assume that the arguments are what you pass in the call when it deduces the declaration. Again it will not know anything else until it later sees the declaration, and may issue a warning then.
Calling a function with to many, or to few, arguments leads to undefined behavior, which is why implicitly declared functions are so dangerous, as well as using an empty argument list when declaring functions.

There is really nothing to understand. This is a legacy C behaviour, which was an extremely lax language. As long as compiler could generate assembly instruction, it would gladly compile your code, and leave it to you to clean up the mess.
This is why it compiles in your case. Compiler can generate instruction to call the function - so it does as asked.

Related

Why does a function that returns int not need a prototype?

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".

Can Function declaration or function prototype affects the working of the program

I am new beginner in the programming world and while I was coding on Functions in C, I came to know that there are three most important parts of the functions namely-
Function declaration or function prototype
Function call
Function definition
But, while I was solving a problem on factorials of a number I came to know in my code that when I am not including function declaration or function protocol in my code above main() then still the code is running and giving the output as 120. So my question is why a function declaration or function prototype is not affecting the output of my program or is it not necessary to include function declaration or prototype above main().
-------Code-----
#include<stdio.h>
#include<conio.h>
// int fact(int);
main()
{
int x;
x=fact(5);
printf("The factorial is =%d",x);
}
int fact(int n)
{
int f=1,i;
for(I=1;i<=n;i++)
f=f*I;
return (f);
}
If you use a function without declaring it, the compiler may provide a default declaration. This is not part of modern C, but compilers may use old standards or be unduly lax in this regard. (It is better to require explicit declarations because it helps reduce mistakes.)
Any declaration of a function must match the definition of the function. The declaration gives the compiler information about how to call the function. If the declaration does not match, things can go wrong. So, yes, the declaration can affect your program; it can break it.
In this case, you got lucky, the default declaration of a function happened to match your function fact. The default declaration is a function that returns int and accepts whatever arguments you pass it, subject to default argument promotions. (Roughly speaking, the default argument promotions are that integers narrower than an int are converted to int, and float values are converted to double. So, if a function returns int and accepts only int and double arguments, it can match the default declaration.)
A good compiler will warn you that a declaration is missing or that a declaration is wrong. Your compiler has “switches” or other options that tell it what sorts of warning and error messages you want. You should ask for lots of warning messages.
Your compiler probably also has switches that say which version of C to use. (There have been several standard versions, most recently 1999 and 2011, and there are some non-standard variants.) You might want to request that your compiler use the C 2011 standard, until you have good reason to change that. (Unfortunately, if you are using Microsoft Visual C, I do not believe it supports C 2011.)

What is the difference between normal assignment(a = b) and passing parameters in terms of forced and unforced variables? [duplicate]

Is it necessary to declare function before using it? Does the compiler give an error if we don't use a function declaration and call it directly. Please answer according to standard C.
If yes then what does it mean that argument of type are converted to int and float to double if arguments to function are not defined?
In ANSI C, 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.
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, you need to define everything before you use it. I think the idea is that it can compile everything in one pass, since it always has all of the information it needs by the time it gets to it.
I'm not sure what you're asking with the second part. If the function isn't defined, it just won't work.
The short answer: in C89/90 it is not necessary, in C99 it is necessary.
In C89/90 the function does not have to be declared in order to be called. For undeclared function the compiler will make an assumption about function return type (assumes int) and about function parameter types (will derive them from the argument types at the point of the call).
In C99 the function has to be previously declared in order to be called. Note, that even in C99 there's no requirement to provide a prototype for the function, only a declaration is needed, i.e. a non-prototype declaration is OK. This means that the compiler no longer has to make any assumptions about the function return type (since the declaration always specifies it explicitly), but it still might have to make assumptions about the function parameters (if the declaration is not a prototype).
The C99 standard in 6.5.2.2 "Function call" describes what happens in a function call expression, including if no prototype has been seen by the compiler for the function:
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
Later, it describes what happens if the function call expression doesn't match what how the function is actually defined:
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.
Clearly, to help ensure correctness, using function prototypes is the right thing to do. Enough such that C++ made requiring function prototypes one of the 'breaking' changes with c.

Is c function prototype mismatch merely a warning

please take a look at my codes below
#include <stdio.h>
void printOut()
{
static int i = 0;
if (i < 10)
{
printOut(i);
}
}
int main(int argc, char *argv[])
{
return 0;
}
i guess there should be an error due to my invoking the non-existed function prototype.Actually, the code compiles well with mingw5 compiler, which is weird for me, then i change to Borland Compiler, i get a warning message said that no printOut function prototype, is this only a warning ? What is more, the code executes well without any pop-up error windows.
In C, a function without any parameters can still take parameters.
That's why it compiles. The way to specify that it doesn't take any parameters is:
void printOut(void)
This is the proper way to do, but is less common especially for those from a C++ background.
Your program's behavior is undefined, because you define printOut() with no parameters, but you call it with one argument. You need to fix it. But you've written it in such a way that the compiler isn't required to diagnose the problem. (gcc, for example, doesn't warn about the parameter mismatch, even with -std=c99 -pedantic -Wall -Wextra -O3.)
The reasons for this are historical.
Pre-ANSI C (prior to 1989) didn't have prototypes; function declarations could not specify the expected type or number of arguments. Function definition, on the other hand, specified the function's parameters, but not in a way that the compiler could use to diagnose mismatched calls. For example, a function with one int parameter might be declared (say, in a header file) like this:
int plus_one();
and defined (say, in the corresponding .c file) like this:
int plus_one(n)
int n;
{
return n + 1;
}
The parameter information was buried inside the definition.
ANSI C added prototypes, so the above could written like this:
int plus_one(int n);
int plus_one(int n)
{
return n + 1;
}
But the language continued to support the old-style declarations and definitions, so as not to break existing code. Even the upcoming C201X standard still permits pre-ANSI function declarations and definitions, though they've been obsolescent for 22 years now.
In your definition:
void printOut()
{
...
}
you're using an old-style function definition. It says that printOut has no parameters -- but it doesn't let the compiler warn you if you call it incorrectly. Inside your function you call it with one argument. The behavior of this call is undefined. It could quietly ignore the extraneous argument -- or it could conceivably corrupt the stack and cause your program to die horribly. (The latter is unlikely; for historical reasons, most C calling conventions are tolerant of such errors.)
If you want your printOut() function to have no parameters and you want the compiler to complain if you call it incorrectly, define it as:
void printOut(void)
{
...
}
This is the one and only correct way to write it in C.
Of course if you simply make this change in your program and then add a call to printOut() in main(), you'll have an infinite recursive loop on your hands. You probably want printOUt() to take an int argument:
void printOut(int n)
{
...
}
As it happens, C++ has different rules. C++ was derived from C, but with less concern for backward compatibility. When Stroustrup added prototypes to C++, he dropped old-style declarations altogether. Since there was no need for a special-case void marker for parameterless functions, void printOut() in C++ says explicitly that printOut has no parameters, and a call with arguments is an error. C++ also permits void printOut(void) for compatibility with C, but that's probably not used very often (it's rarely useful to write code that's both valid C and valid C++.) C and C++ are two different languages; you should follow the rules for whichever language you're using.

Must declare function prototype in C? [duplicate]

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’.

Resources