C prototype functions - c

As a beginner to C, I can understand the need for function prototypes in the file, but am unsure of a couple things.
First, does every function call outside of the main require a prototype declaration? Are there any conditions where that can change?
Second, do you need a separate function prototype for method overloads?

Function calls in C don't require a prototype to be visible but it is highly recommended that a correct prototype is in scope.
The reason for this is that if the function definition doesn't match the types of the function arguments after the default function argument promotions are performed you are highly likely to get undefined behavior.
Having the correct prototype visible means that the compiler can check the arguments of a function call and warn the programmer if there is a mismatch.
C doesn't allow functions to be overloaded so you can only have a single prototype for any function name.
Default argument promotions can cause unexpected mismatches.
E.g.
int main(int argc, char **argv)
{
short s = 5;
float f = 2.3f;
x(s, f); // x implicitly declared; default argument promotions performed
return 0;
}
int x(short t, float g) // Error: called with an int and a double
{
return (int)(t + g);
}
In the function call, because x has no visible prototype (yet), s will be promoted to int and f will be promoted to double. These are default argument promotions. This then causes a mismatch when the function is defined with a prototype that takes a short and a float even though these are the original types of the arguments that were passed in.
Functions that take a variable number of arguments (i.e. use , ... syntax) must always have a visible prototype at the point at which they are called.

Others have already pointed out that C doesn't require prototypes for functions. I'll just add a couple minor points.
First of all, without a prototype, the arguments to a function always undergo "default promotions" before being passed as parameters, so (for example) all the smaller integer types get promoted to int, and float gets promoted to double. Therefore, without a prototype, it's impossible for a function to receive (for example) a char, short, or float. If the function is defined to receive one of those types, there will be a mismatch between what's passed and what the function expects, giving undefined behavior (any other mismatch gives undefined behavior as well).
Second, if a function is defined with a variable argument list, then you do need a prototype for it, or else calling it will result in undefined behavior.

No, functions are not required to have prototypes. However, they are useful as they allow functions to be called before they are declared. For example:
int main(int argc, char **argv)
{
function_x(); // undefined function error
return 0;
}
void function_x()
{
}
If you add a prototype above main (this is usually done in a header file) it would allow you to call function_x, even though it's defined after main. This is why when you are using an external library that needs to be linked, you include the header file with all the function prototypes in it.
C does not have function overloading, so this is irrelevant.

No. In C not every function requires a prototype. BUT it is good practice to include it. Prototypes help the compiler catch errors.
Of course some C compilers, by default complain if prototypes are missing before the function call, but this behavior is not necessarily a standard.
The above logic applies to overloads too.
Of-course, since you are new to C. I think you better go and look up the difference between a Prototype and Definition of a function to make full sense.

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

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.

Unspecified number of parameters in C functions - void foo()

I read here that in C void foo() means a function foo taking an unspecified number of arguments of unspecified type.
Can anyone give me or point me to an example where a C function takes an unspecified number of arguments? What can this be applied to in C? I couldn't find anything on the web.
That's an old-style function declaration.
This declaration:
void foo();
declares that foo is a function returning void that takes an unspecified but fixed number and type(s) of arguments. It doesn't mean that calls with arbitrary arguments are valid; it means that the compiler can't diagnose incorrect calls with the wrong number or type of arguments.
Somewhere, perhaps in another translation unit (source file), there has to be a definition of the function, perhaps:
void foo(x, y)
long x;
double *y;
{
/* ... */
}
This means that any call to foo that doesn't pass two arguments of type long and double* is invalid, and has undefined behavior.
Prior to the 1989 ANSI C standard, these were the only kind of function declaration and definition available in the language, and the burden of writing correct function calls was entirely on the programmer. ANSI C added prototypes, function declarations that specify the types of a function's parameters, which allow compile-time checking of function calls. (This feature was borrowed from early C++.) The modern equivalent of the above would be:
void foo(long x, double *y);
/* ... */
void foo(long x, double *y) {
/* ... */
}
Old-style (non-prototype) declarations and definitions are still legal, but they're officially obsolescent, which means that, in principle, they could be removed from a future version of the language -- though since they're still around in the 2011 standard I don't know that that will ever actually happen.
There is no good reason to use old-style function declarations and definitions in modern C code. (I've seen arguments for using them in some corner cases, but I find them unconvincing.)
C also supports variadic functions like printf, which do take an arbitrary number of arguments, but that's a distinct feature. A variadic function must be declared with a prototype, which includes a trailing , .... (Calling a variadic function with no visible prototype isn't illegal, but it has undefined behavior.) The function itself uses macros defined in <stdarg.h> to process its parameters. As with old-style function declarations, there is no compile-time checking for arguments corresponding to the , ... (though some compilers may check some calls; for example gcc warns if the arguments in a printf call are inconsistent with the format string).
This literally means that you are not telling the compiler what arguments the function takes, this means that it will not protect you from calling it with any arbitrary set of arguments. You would need to say in the definition precisely what arguments are actually taken for the function to be implemented however.
You could for example use this if you were generating a header file to describe a foreign function in external code, however you did not know what the function's signature actually was, it would still then be callable using your header but if you provide the wrong arguments in the call results are undefined.
The declaration void foo(); is not necessarily the same thing as a function that takes a variable number of arguments.
All that it is is a function declaration that indicates nothing about the number of arguments the function takes (actually, this is not exactly true, see below about argument promotions). The declaration isn't a function prototype, which provides information about the number and types of the parameters (using an ellipsis to indicate variable length parameters).
The function definition (where the body of the function is provided) might take a fixed number of arguments, and might even have a prototype.
When such a function declaration is used, it is up to the programmer making a call to foo() to get the arguments that foo() expects (and their types) correct - the compiler has no information about the argument list foo() requires. It also restricts the type of parameters that the function definition can use because when the function is called without a prototype, therefore the default argument promotions will be applied to the arguments at the function call. So a function that's declared without a prototype can only expected to get promoted arguments.
See the following C99 standard sections for some details:
6.7.5.3/14 "Function declarators (including prototypes)
...
The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the
number or types of the parameters is supplied.
...
6.5.2.2 Function calls
...
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. If the function is defined with a type that
includes a prototype, and either the prototype ends with an ellipsis
(, ...) or the types of the arguments after promotion are not
compatible with the types of the parameters, the behavior is
undefined. If the function is defined with a type that does not
include a prototype, and the types of the arguments after promotion
are not compatible with those of the parameters after promotion, the
behavior is undefined, except for the following cases:
one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is
representable in both types;
both types are pointers to qualified or unqualified versions of a character type or void.
The C function calling standard allows for a function to be called with zero or more arguments and the number of arguments may or may not match the function interface.
The way this works is that it is up to the caller to adjust the stack after the called function returns rather than the called function adjusting the stack unlike other standards such as Pascal which require the called function to manage the stack adjustment properly.
Because the caller knows what arguments and their types have been pushed onto the stack before the called function is called and the called function does not, it is up to the caller to clear the pushed arguments from the stack after the called function returns.
With updated C standards, the function call interface description has become more complex in order to allow the compiler to detect and report interface problems that the original K&R C standard allowed to go undetected by the compiler.
The standard now is that you specify variable argument lists using elipsis notation of three periods or dots after the last known and specified argument in the called functions interface specification or declaration.
So you would see something like the following for some of the Standard C Library I/O functions:
int sprintf (char *buffer, char *format, ...);
This indicates that the function sprintf requires that the first argument be a char pointer to a buffer, the second argument be a char pointer to a format string, and there may be other additional arguments. In this case any additional arguments would be what are needed to be inserted for the print format specifiers in the format string. If the format string is just a text string with no format specifies (something like %d for an integer for instance) then there would be no other arguments.
The newer C Standards specify a set of functions/macros for the use with variable argument lists, the varg functions. With these functions/macros the called function can step through the variable part of an argument list and process the arguments. These functions look something like the following:
int jFunc (int jj, char *form, ...)
{
va_list myArgs;
int argOne;
va_start (myArgs, form);
argOne = va_arg (myArgs, int);
va_end (myArgs);
return 0;
}
The problem that we have with variable argument lists is that C does not have a way of communicating the variable argument or even how many arguments. So the designer of the function has to provide a mechanism. In the case of the C Standard Library I/O functions this is done with the format that indicates the number of arguments following the format string by specifying format specifiers for each argument. And since there is nothing that does a consistency check, you can end up with a format string that specifies more or less than the actual arguments resulting in either garbage output or less output than expected.
Since modern C compilers have some degree of backwards compatibility for old C source code, that means that you can use some of the older constructs and the compiler will allow it though hopefully with a warning.
The new function interface specifications are designed to reduce the chances of using a function incorrectly. So the new standards recommend that you use the function interface declaration so that the compiler can help you by detecting interface problems and incorrect variable usage in the function call.
However if you want to be a risk taker you do not have to use this safety net so if you like you can just define a function with an empty argument list and wing it.
You might also find an answer I put into this question about currying in C that uses variable argument lists along with a way to determine how many arguments are provided.
As mentioned in many other answers, a function taking an unspecified number of arguments of unspecified type just means it's caller doesn't know about its definition. It's completely different from variadic functions where you must define with ... and then use va_list in stdarg.h to obtain the arguments
It's actually common in the past and there are many standard functions using that feature, for example open()/openat()/_open() with an optional last parameter
fd = open(filename, O_RDONLY);
fd = open(filename, O_CREAT | O_WRONLY, 0777);
See open() function parameters
main() is also a function that can receive varying number of arguments
int main();
int main(int argc, char **argv);
int main(int argc, char **argv, char **envp);
int main(int argc, char **argv, char **envp, char **apple);
In fact the Windows x64 calling convention is designed to support such unspecified number of arguments so it's a bit unfortunate for most modern usecases

Why is this legal in C?

I am writing a toy C compiler for a compiler/language course at my university.
I'm trying to flesh out the semantics for symbol resolution in C, and came up with this test case which I tried against regular compilers clang & gcc.
void foo() { }
int main() { foo(5); } // foo has extraneous arguments
Most compilers only seem to warn about extraneous arguments.
Question: What is the fundamental reasoning behind this?
For my symbol table generation/resolution phase, I was considering a function to be a symbol with a return type, and several parametrized arguments (based on the grammar) each with a respective type.
Thanks.
A function with no listed arguments in the prototype is deemed to have an indeterminate number, not zero.
If you really want zero arguments, it should be:
void foo (void);
The empty-list variant is a holdover from ancient C, even before ANSI got their hands on it, where you had things like:
add_one(val)
int val;
{
return val + 1;
}
(with int being the default return type and parameter types specified outside the declarator).
If you're doing a toy compiler and you're not worried about compliance with every tiny little piece of C99, I'd just toss that option out and require a parameter list of some sort.
It'll make your life substantially easier, and I question the need for people to use that "feature" anyway.
It's for backward compatibility with ancient C compilers. Back before the earth cooled, all C function declarations looked roughly like:
int foo();
long bar();
and so on. This told the compiler that the name referred to a function, but did not specify anything about the number or types of parameters. Probably the single biggest change in the original (1989) C standard was adding "function prototypes", which allowed the number and type(s) of parameters to be declared, so the compiler could check what you passed when you called a function. To maintain compatibility for existing code, they decided that an empty parameter list would retain its existing meaning, and if you wanted to declare a function that took no parameters, you'd have to add void in place of the parameter list: int f(void);.
Note that in C++ the same is not true -- C++ eliminates the old style function declarations, and requires that the number and type(s) of all parameters be specified1. If you declare the function without parameters, that means it doesn't take any parameters, and the compiler will complain if you try to pass any (unless you've also overloaded the function so there's another function with the same name that can take parameters).
1 Though you can still use an ellipsis for a function that takes a variable parameter list -- but when/if you do so, you can only pass POD types as parameters.
You haven't provided a prototype for the foo function, so the compiler can't enforce it.
If you wrote:
void foo(void) {}
then you would be providing a prototype of a function that takes no parameters.
gcc's -Wstrict-prototypes will catch this. For an error, use -Werror=strict-prototypes. The standard never specifies whether something should be a warning or an error.
Why is this legal in C?
First just to clarify the C Standard does not use the word legal.
In the C terminology, this program is not strictly conforming:
void foo() { }
int main() { foo(5); } // foo has extraneous arguments
When compiling this program, no diagnostic is required because of the function call foo(5): there is no constraint violation. But calling the function foo with an argument invokes undefined behavior. As any program that invokes undefined behavior, it is not strictly conforming and a compiler has the right to refuse to translate the program.
In the C Standard, a function declaration with an empty list of parameters means the function has an unspecified number of parameters. But a function definition with an empty list of parameters means the function has no parameter.
Here is the relevant paragraph in the C Standard (all emphasis mine):
(C99, 6.7.5.3p14) "An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters."
The paragraph of the C Standard that says the foo(5) call is undefined behavior is this one:
(C99, 6.5.2.2p6) "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."
And from (C99, 6.9.1p7), we know the definition of foo does not provide a prototype.
(C99, 6.9.1p7) "If the declarator includes a parameter type list, the list also specifies the types of all the parameters; such a declarator also serves as a function prototype for later calls to the same function in the same translation unit. If the declarator includes an identifier list,the types of the parameters shall be declared in a following declaration list."
See the Committee answer to the Defect Report #317 for an authoritative answer on the subject:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_317.htm

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