More How to
Program in C
### 7.0 How to use libraries
----------------------------------------------------------------------
Libraries are collections of often used
procedures. Even more, these procedures can do very difficult
tasks for us, which to implement by ourselves would take hours
(days,weeks,months....).
So, why not to write a example program,
which uses a library procdedure, and header files? And with this
example we will get an error, which will help us to understand
some special context.
At first, let's have a closer look to a
stripped version of our first program (I have left of the code
to detect the kind of compiler, you use...)
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[] )
{
printf( "Hello, Hackers!\n" );
}
Do you see, what is special with this one?
No? Remember the text above! No clue?
"Before using a function, you have to write down a prototype
of it." There are two functions used in this program:
main()
printf()
The prototype of "printf" is
defined in the header file
/usr/include/stdio.h
If you give the command
grep printf /usr/include/stdio.h
You will see a couple of prototypes, not
only of printf itself, but of similar functions.
What's with main() ?
This one is special!!! It is the mother/the
father of all functions. It is the point where execution of the
program starts. There can be only one function of this name but
it must be there. So, to be convenient, the prototype of this
special function is directly "burned in" the compiler
itself.
Let's change the program to use more than
main(). Let's put in the use of header files defined by
ourselves and a call to a library function. Change the above
source code to:
#include<stdio.h>
#include<stdlib.h>
#include "myprocs.h"
int main(int argc, char *argv[] )
{
showme( "How to hack!" );
}
void showme( char *mywish )
{
printf( "%s\n", mywish );
printf( "%f\n", sin(35.0));
}
Save this as "hh2.c" with your
editor. Next use your editor to create a file
with the contents:
void showme( char *mystring );
Save it as "myprocs.h".
Now give the command:
cc hh2.c -o hh2
Time to learn! There are errors.... The output of the compiler
looks something like :
hh2.c: In function `showme':
hh2.c:14: warning: type mismatch in implicit
declaration for
built-in function `sin'
/tmp/cca008671.o: In function `showme':
/tmp/cca008671.o(.text+0x36): undefined reference
to `sin'
collect2: ld returned 1 exit status
Let's see what the compiler is trying to
tell us. First line: The compiler tells us that there is
something wrong inside the function showme().
Second line: There is a warning! Be warned!
DON'T think: "Oh, this is only a warning, no error, so:
proceed!" But a warning is the error of tomorrow. But it
is more difficult to find those warning based errors. This warning
said, that there is a type mismatch in the implicit call of the
built-in function sin.
Type mismatch? A type mismatch is
if you have ordered a really nice strawberry ice cream and will
get a hot dog instead. Or in other words: If a function wants
to get a text and you call it with a number. The compiler said,
this happened to "sin". Let's have a look. Remember
school days. What was it? "sin" stands for sine. And
the argument for sine was a floating point number. So we are
right here. "It is a compiler error!" Ah, wait! WE
are hackers, so WE want to learn by making errors, not the compiler!
What happens to the ice cream example above? They gave you a
hot dog instead. The reasons? First: You have ordered an ice
cream, they gave you a hot dog. They have made an error, and
you have learned nothing. Better case: You have mumbled "Strawberry
ice cream, please." They have understood "hot dog"
and gave you what they think, you want. Your error, you have
the chance to learn ;-)
In this case, we have mumbled "sin(),
please". The compiler doesn't understand that correctly,
because: There is no prototype for it.
(Note: An "implicit call" to
a function is a call without having informed the compiler before,
how it looks like (no prototype ofr it). This goes often hand
in hand with "type mismatch" errors or warnings.)
Where should I get the prototype definition?
Simply, as in most cases it is absolutely
sufficient to type in the command:
man sin
My Linux box produces this answer:
----------------------------------------------------------------------
SIN(3)
Linux Programmer's Manual
SIN(3)
NAME
sin - sine function
SYNOPSIS
#include <math.h>
double sin(double x);
DESCRIPTION
The sin() function returns
the sine of x, where x is given
in radians.
RETURN VALUE
The sin() function returns
a value between -1 and 1.
CONFORMING TO
SVID 3, POSIX, BSD 4.3,
ISO 9899
SEE ALSO
acos(3), asin(3), atan(3),
atan2(3), cos(3), tan(3)
June 8, 1993
1
----------------------------------------------------------------------
Look at the text after SYNOPSIS.
There is a line with "#include <math.h>" !!!
Tada! This instructs the compiler to read the header file "math.h"
from the system directory /usr/include/ (or something like that,
use the "whereis "math.h" command to get the correct
path on your computer for this header) before proceeding.
Insert such a line after the other #include"-lines
in our example and compile it again.
Now, the compiler don't produces that "mismatch
error" again, this one is fixed. But the other one remains:
/tmp/cca009281.o: In function `showme':
/tmp/cca009281.o(.text+0x36): undefined reference
to `sin'
Looks very strange....
While the compiler is translating source
code for us, it needs some temporary files to write down things
to remember. These files have names like "/tmp/cca009281.o".
When the compiler rereads its notes, it realizes that there is
a CALL to sin(), but no one has defined this function. And now?
DON'T PANIC! sin() is part of the math
library. Someone else has written down and precompiled the source
code for a sine function for us and has included it into the
math library.