You are on page 1of 3

"make hello" works fine with that. Why? Because the file /usr/include/stdio.

h de
fines FILE (among a lot of other things). Here's a good rule to follow: you will
almost ALWAYS need stdio.h. Whenever the man page for a function you want menti
ons including some file, it's a pretty good bet that your program is not going t
o work without it. And there may even be more to do. Look at this:
#include <stdio.h>
#include <math.h>
main ()
{
printf("pi = %.5f\n", 4 * atan(1.0));
}

We looked up the atan function and found it needs math.h. We've told the complil
er to include it. Trust me, the program is right. But..
$ gcc -o pi pi.c
/tmp/ccLmoMxc.o(.text+0x33): In function `main':
: undefined reference to `atan'
collect2: ld returned 1 exit status

What we need here is a special compiler flag:


gcc -o pi -lm pi.c

"lm" tells it to link in the math libraries. Math libraries? Sure, you didn't th
ink C by itself knows how to do arc tangents, did you? C by by itself doesn't kn
ow much. Most of its functions - the things you can use - come from external lib
raries that get linked in. How would you know when you need to use a special lib
rary? It's just something you have to learn. Usually, if there is a special link
er flag, the man page will have told you. In the case of atan, it does not, so y
ou just need to remember that you need "-lm" when you see "#include <math.h>" me
ntioned.
Make files
With just this much knowledge, you can actually write C programs. You don't need
make files (though make files are of course very useful for bigger programs). I
f the program needs no special compiler flags, "make" is smart enough to know wh
at to do all by itself, as we saw earlier. As you write bigger programs, you'll
find that "gcc -Wall" and "lclint" will help you spot your mistakes. But let's "
make" something a bit more complicated. It's two files, and we'll be using a new
compiler switch:
$ cat pi.c
#include <math.h>
mypi()
{
printf("pi = %.5f\n", 4 * atan(1.0));
}
$ cat hello.c
#include <stdio.h>
main ()
{
mypi();
}
$ gcc -c pi.c
$ gcc -c hello.c
$ gcc -lm -o hello hello.o pi.o
$ ./hello
pi = 3.14159

That's all good, and it works, but all those gcc's would get annoying real fast.
This is where we use "make".
$ cat Makefile
pi.o: pi.c
gcc -c pi.c
hello.o: hello.c
gcc -c hello.c
hello: hello.o pi.o
gcc -lm -o hello hello.o pi.o

You need TABS after each ":" and before the gcc's on the lines that follow
each "rule". Basically, a makefile says "to make x, you need these files, and
you run this command

target : TAB files needed


TAB command needed

Leave out tabs and make will complain:


Makefile:5: *** missing separator. Stop

But we got the tabs right, so now we can do "make hello" and it works:
$ make hello
gcc -c hello.c
gcc -c pi.c
gcc -lm -o hello hello.o pi.o
$ ./hello
pi = 3.14159
$

You are going to make more mistakes. If you are like most of us, pointers and in
direct pointers (char *this, char **that) are going to confuse you, and you'll m
isuse them. Lint and gcc -Wall will help you somewhat, but you'll still probably
screw up. You'll forget that you are referencing something on a long overwritte
n stack. You'll blithely dereference past the end of an array and your programs
will crash as they get killed off for trying to change somebody else's memory sp
ace. Don't feel badly, other people have stumbled and lurched down the same path
before you. Buy a beginner's C book, and have at it.
Here's some references that can help:

You might also like