[Courses] [C] lesson8 questions & answers

Laurel Fan laurel at sdf.lonestar.org
Sat Nov 9 17:08:47 EST 2002


On Sun, Nov 10, 2002 at 03:35:48PM -0500, Morgon Kanter wrote:
> First, my question:
> Hey, why do we keep doing
> #include <stdio.h>
> at the beginning of programs?

The reason has to do with the difference between including a header
file and linking with a library.  A header file does not include the
actual code for a function.  You can verify this by looking at the
actual header file.  stdio.h is probably /usr/include/stdio.h.  If you
look in there, all it says about printf is:

/* Write formatted output to stdout.  */
extern int printf (__const char *__restrict __format, ...) __THROW;

This is the declaration of the function (and a nice comment to tell
you what printf is).  It tells you the type of the return value and
the type of the arguments.  The actual code for printf is not in
stdio.h.  So, where is it?

printf (and everything else in stdio.h) is in the C library, which is
normally in a file called libc.so.<something>.  If you use the ldd
command on one of your programs, it will probably tell you where it
is, for example:

> ldd a.out
        libc.so.6 => /lib/libc.so.6 (0x40020000)

This tells me that a.out is "linked with" libc.so.6.  This file does
not contain the source code for printf, but it does contain printf
compiled in a format similar to that of an executable.  Generally, all
C programs are linked with libc.  What linking means is that when I
compiled my code to get a.out, the compiler figured out that I used
functions that were in libc, and included this information in the
executable.

So, why does printf work even when you don't include stdio.h?  If the
compiler comes across a function it doesn't know about, it assumes
that you will be linking with a library that contains it.  This is
called an implicit declaration.  (If you use the -Wall option, which
I've described in a different email, gcc will warn you about implicit
declarations).  If you are (in this case, because printf is in libc,
which is automatically linked), then everything is fine.

It's usually good style to avoid implicit declarations.  One reason is
that it doesn't always work.  Another reason is that it tells people
reading your code, and tools such as makedepend, what files or
libraries your code depends on.

Here's another example illustrating the difference between compiling
and linking.  Suppose I have this code:

#include <stdio.h>

int main()
{
  printf("%f\n", pow(1, 2));
  return 1;
}

If I try to compile it, I get:

> gcc -Wall test.c
test.c: In function `main':
test.c:5: warning: implicit declaration of function `pow'
/tmp/ccU5TCho.o(.text+0x11): In function `main':
: undefined reference to `pow'
collect2: ld returned 1 exit status

First, it warns me about implicit declarations.  I can fix this by
including math.h, which contains the declaration for pow:

#include <stdio.h>
#include <math.h>

int main()
{
  printf("%f\n", pow(1, 2));
  return 1;
}

But if I compile that, I still get this error:

> gcc -Wall test.c
/tmp/ccJxetUM.o(.text+0x1d): In function `main':
: undefined reference to `pow'
collect2: ld returned 1 exit status

I have included math.h, so it found the declaration of pow(), but I
still need to link with the math library, so it can find the
implementation of pow().  I do this with the compiler argument -lm
(which means link with the "m" library, which is what the math library
happens to be called):

> gcc -Wall -lm test.c

Which works fine, and so does the executable it produces:

> ./a.out
1.000000

-- 
laurel at sdf.lonestar.org
http://dreadnought.gorgorg.org



More information about the Courses mailing list