Why is a function declared near the top of a source file? - c

I'm working through K & R to learn programming. Going well so far, but I'm unclear about the role of a line of code from section 1.8 (functions).
In section 1.8, the authors show you how to create a function to raise one integer to the power of another integer.
I've pasted the code below, as it was written in the book. Everything outputs fine. But I don't know why they've included this line at the top:
int power(int m, int n);
The book doesn't mention it, apart from saying that the program will raise integer m to the power n. If I remove the line from the code, the program still outputs as it should.
If I understand this correctly, the line
int power(int base, int n)
creates the function, and the braces underneath define the function. Then the braces under main call the function to output the chart.
So all that seems to make sense. But I don't see what the very top line does.
It could be extraneous, but it seems far more likely that I'm missing something. Can anyone enlighten me as to why that line is there?
#include <stdio.h>
int power(int m, int n);
/* test power function */
main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3, i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p = 1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}

The first line is the declaration of the function. The block of code at the bottom is the definition of the function.
Starting with the 1999 version of the ISO C standard, it's illegal (a constraint violation) to call a function without a visible declaration; the declaration must precede the call.
For a simple program like this one, you could just write the full definition of power() before the definition of main() (since a definition also provides a declaration), but for more complex cases (such as recursive calls) you often need to provide a separate declaration.
For larger programs, it's common to collect all the function declarations in a header file (foo.h, for example), and the corresponding definitions in a source file (foo.c, for example). A #include "foo.h" directive is used to make the declarations visible in other files. You'll see that kind of thing later in the book.
(In the 1990 and earlier versions of C, which is what K&R2 covers, there are cases where you can call a function without a visible declaration -- but it's still a very good idea to provide explicit declarations anyway.)
Incidentally, the declaration of the main program should really be int main(void) rather than just main().
Terminology: a "prototype" is a function declaration that specifies the types of the parameters.
int power(int base, int n); /* a declaration that's also a prototype */
int power(int, int); /* likewise */
int power(); /* a declaration but not a prototype */
(Parameter names are required in a definition, but optional in a standalone declaration.)
As a special case, a prototype for a function with no parameters uses (void), since empty parentheses already mean a non-prototype declaration. So int main(void) is a prototype, but int main() isn't.
Non-prototype declarations are "obsolescent", meaning that they could in theory be removed from a future language standard. But they've been obsolescent since 1989, and even in the new 2011 ISO C standard the committee hasn't seen fit to remove them.

int power(int m, int n);
is a declaration of the power function in its prototype form. A function declaration informs the compiler of the number of parameters the function has, the type of the function parameters and the type of the function return value.
In C you cannot use a function identifier before it has been declared.

It's a forward declaration which makes the function interface public as the function is used before it is actually implemented below main().
Header files, which you #include provide a similar functionality of making the callable API public---but the code is then commonly supplied in a library rather than via the same compilation unit as it is here in this single-file example of the K&R Intro chapter.

If you don't include that line at the top, when the program reaches power(2,i) in main power has not been declared yet. Programs are read from top to bottom, and by putting the declaration at the top, the compiler knows that "a definition is coming".

That line is just the function prototype. It's a forward declaration that allows code to be able to use some function with that signature that will exist when everything is linked together. Without it, the main() function will attempt to use the power() function but the compiler is not aware of it yet since it isn't actually defined later in the source file.

That line at the top that you are referring to is a function prototype. The ONLY thing it is there for is so that the compiler can check your work, that is, to make sure you are using the function correctly by passing the right types and number of arguments. That's all it is for. That is why you can remove it and the code still compiles - all you are doing by removing it is removing the compiler's reference so it can't check your work. And if you do remove it, then there is the possibility that you could pass the wrong type of argument(s) and cause a hard to find run time error or program crash. But leaving it in allows the compiler to flag such an error at compile time saving you some grief. And saving someone some grief is a good thing.
Later, with the C99 standard, they decided to make it mandatory to provide a function prototype (or else define the function first) in order for the code to compile, thus forcing you to let the compiler check your work.

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

Strange function definition [duplicate]

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.

C function weird syntax [duplicate]

I'm relatively new to C. I've come across a form of function syntax I've never seen before, where the parameter types are defined after that parameter list. Can someone explain to me how it is different than the typical C function syntax?
Example:
int main (argc, argv)
int argc;
char *argv[];
{
return(0);
}
That's the old-style syntax for parameter lists, which is still supported. In K&R C you could also leave off the type declarations and they would default to int. i.e.
main(argc, argv)
char *argv[];
{
return 0;
}
would be the same function.
What's also interesting is the calling convention difference of functions with, and functions without a prototype. Consider an old style definition:
void f(a)
float a; {
/* ... */
}
In this case, the calling convention is that all arguments are promoted before being passed to the function (for example, a float argument is first promoted to double, before being passed). So if f receives a double but the parameter has type float (which is perfectly valid) the compiler has to emit code that converts the double to a float prior to executing the function's body.
If you include a prototype, the compiler does not do such automatic promotions anymore and any data passed is converted to the types of the parameters of the prototype as if by assignment. So the following is not legal and results in undefined behavior:
void f(float a);
void f(a)
float a; {
}
In this case, the function's definition would convert the submitted parameter from double (the promoted form) to float because the definition is old-style. But the parameter was submitted as a float, because the function has a prototype. For example, clang gives
main.c:3:9: warning: promoted type 'double' of K&R function parameter is not compatible with the parameter type 'float' declared in a previous prototype [-Wknr-promoted-parameter]
Your options of solving the contradictions are the two following:
// option 1
void f(double a);
void f(a)
float a; {
}
// option 2
// this declaration can be put in a header, but is redundant in this case,
// since the definition exposes a prototype already if both appear in a
// translation unit prior to the call.
void f(float a);
void f(float a) {
}
Option 2 should be preferred if you have the choice because it gets rid of the old style definition up front. If such contradicting function types for a function appears in the same translation unit, the compiler will usually tell you (but is not required). If such contradictions appear over multiple translation units, the error will possibly go unnoticed and can result in hard to predict bugs. It is best to avoid these old style definitions.
This is the so caller K&R style or old-style declaration.
Note, that this declaration is significantly different from the modern declaration. K&R declaration does not introduce a prototype for the function, meaning that it doesn't expose the types of the parameters to the outside code.
There is no difference, it is just that that is the old syntax for function declarations in C -- it was used pre ANSI. Never write such code unless you plan to give it to your friends from the 80's. Also, never depend upon implicit type assumptions (as another answer seems to suggest)
While the old syntax for function definition still works (with warnings, if you ask your compiler), using them does not provide function prototypes.
Without function prototypes the compiler will not check if the functions are called correctly.
#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }
int bar(x)
double x;
{ return printf("%f\n", x); }
int main(void)
{
foo(42); /* ok */
bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
return 0;
}
When the program is run, the output on my machine is
$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
Its just the same but old fashion. You probably found it is some old, legacy code.
Old or not, I would argue what is old and what not.. like the pyramids are ancient, but none of today’s so-called scientists have a clue how they were made. Looking back, old programs still work today without memory leaks, but these "new" programs tend to fail more than often. I see a trend here.
Probably they saw functions as structs which have an executable body. Knowledge of ASM is needed here to solve the mystery.
Edit, found a macro which indicates you do not need to supply argument names at all.
#ifndef OF /* function prototypes */
# ifdef STDC
# define OF(args) args
# else
# define OF(args) ()
# endif
#endif
#ifndef Z_ARG /* function prototypes for stdarg */
# if defined(STDC) || defined(Z_HAVE_STDARG_H)
# define Z_ARG(args) args
# else
# define Z_ARG(args) ()
# endif
#endif
Here is an usage example, library is zlib-1.2.11.
ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
So my second guess would be for function overloading, otherwise these arguments had no use. One concrete function, and now infinite amount of functions with same name.

Call a function without argument, although it needs one [K&R-C]

It's K&R-C and here is the code: http://v6shell.org/history/if.c
Look at the main-Method. There is this line "if(exp())".
But the function exp is declared as: exp(s). So it needs an argument.
Why does this work? And why would you do this?
Ultimately, it is a bug in the Unix V6 shell support command, if.
The code for the function is:
exp(s) {
int p1;
p1 = e1();
if (eq(nxtarg(), "-o")) return(p1 | exp());
ap--;
return(p1);
}
The function parameter s, implicitly of type int (as is the function iteself), is actually unused in the function, so the bug is the presence of s, not the absence of an argument in the calls to exp(). All the calls with zero actual arguments are correct.
If you look at the definition:
exp(s) {
int p1;
p1 = e1();
if (eq(nxtarg(), "-o")) return(p1 | exp());
ap--;
return(p1);
}
s is not used
C doesn't require compile time type checking. It doesn't even require function parameters to be checked. Everything is a/series of bytes
Why does C not do any of those checks? From what I hear it's 'cause during first few years of C, computers were fairly weak. Doing those checks would require multiple passes to scan the source code, which basically increases compile time by a magnitude of n passes. So it just does a single pass, and takes every name as is, which is why function overloading is not supported
So if the definitions did make use of s in some way, you would most likely get some horrible runtime error with wonderful outputs to the console
This is because in c
The compiler will not be able to perform compile-time checking of argument types and arity when the function is applied to some arguments. This can cause problems
Calling an undeclared function is poor style in C (See this) and illegal in C++
for example-
#include<stdio.h>
void f(int x);
int main()
{
f(); /* Poor style in C, invalid in C++*/
getchar();
return 0;
}
void f(int x)
{
printf("%d", x);
}
This program will work but shouldn't be used.See this Wiki link for more.

Resources