Thanks to all of you
.
But I have a small question.I tried to save a program in C with the
".h"extention.I did not include the header files.I just wrote a few
functions.Then i included the file as what we do include our header
files.It just worked fine.Here I have both declared and defined the
functions.
But when I saved the same program with ".C" extention and include that
file in the program it also works the same way...
Have the really succeeded in saving my program as a header file in
the first case???
Am asking this because both the defn and declaration is done there
itself..and no linking is required in this case and that does not make
any diff b/w my ".h" and ".c" files when included.
The whole matter of using .h to mark a file as a header file and .c to
mark a file as a source file is a matter of convention, not a
requirement of the C language itself. As far as the C language is
concerned, you can include a .h file, or a .c file, or anything else,
as long as the contents of that file are legal C code. You don't even
have to #include any files at all if you aren't using any functions
defined outside of your particular program.
It is true that many development tools make the distinction between .h
and .c files, but that's because the convention has become so common
over the years. Also, not all platforms even allow you to name a file
so that it has a .h or .c extension. HP's MPE file system uses the
naming convention file.account.user, so if I created a header file
containing types and prototypes for a networking module, the include
directive would look something like
#include "netdfs.dev.jbode"
The standard library headers (stdio.h, stdlib.h, math.h, etc.) are
treated as special cases, so that you can use
#include <stdio.h>
on any system, including systems like MPE where stdio.h is not a legal
filename, and the right file contents will be loaded.
It is the generally accepted practice that #include files only contain
macro definitions, type definitions, and function prototypes. In
other words, these files define the *interface* to a module or
library, with the implementation of that module or library appearing
in separate source files. The primary reasons for doing this are that
it makes large projects easier to manage, and permits the same code to
be used easily in multiple projects. You break the project down into
a number of modules, implement each module in one or more source
files, compile each module into separate object files or libraries,
and define an interface to each module so other modules may use it.
Each module can be compiled and tested separately, and changes made to
any one module will have little or no effect on other modules if no
changes to the interface are necessary. If you write a
general-purpose module, it can be linked into a number of projects
(just as almost every C program uses printf() or fopen()).
There's no language requirement saying you *can't* put function
definitions in an included file, but there are several good reasons
for not doing so. First of all, function names are exported to the
linker unless you declare them as "static", so if you link two files
together that include the same function definition, you may get a
linker error.
For example, say you have the following files:
/* foo.h */
int foo (void)
{
return 1;
}
/* bar.c */
#include <stdio.h>
#include "foo.h"
int bar (void)
{
int x = foo();
return x;
}
/* main.c */
#include <stdio.h>
#include "foo.h"
int main (void)
{
extern int bar (void);
printf ("bar() returns %d\n", bar());
printf ("foo() returns %d\n", foo());
return 0;
}
Here's what happens when I try to build this in Cygwin using gcc:
jbode@JBODE-2K ~/cstuff/badpractice
$ gcc -o bad main.c bar.c
/cygdrive/c/WINDOWS/TEMP/ccYJ0xkP.o(.text+0x0):bar.c: multiple
definition of `foo'
/cygdrive/c/WINDOWS/TEMP/ccjj5LwY.o(.text+0x0):main.c: first defined
here
collect2: ld returned 1 exit status
The ld linker is complaining because the *definition* of the function
foo() appears in both main.c and bar.c. It's not smart enough to know
that the function is the same in both files, and that one of the
definitions can be safely ignored. You don't want to put global
variable definitions in included files for the same reason.
Another reason for not doing this is that the included file has to be
parsed and compiled every time it appears. So if you include a
hundred-line function in 20 different source files, that same function
has to be parsed and compiled 20 times. And if that function
definition changes, *all* the files that include it must be
recompiled.
Here's the right way to structure the example given above:
/* foo.h -- defines the interface to foo() */
#ifndef FOO_H /* These two lines prevent a file from being included*/
#define FOO_H /* more than once in the same translation unit */
extern int foo (void);
#endif
/* foo.c -- implements the function foo() */
#include "foo.h"
int foo (void)
{
return 1;
}
/* bar.h -- defines interface to bar() */
#ifndef BAR_H
#define BAR_H
extern int bar (void);
#endif
/* bar.c -- implements function bar() */
#include "bar.h"
#include "foo.h" /* remember this is the *prototype*, not the
definition */
int bar (void)
{
int x = foo();
return x;
}
/* main.c -- calls foo() and bar() functions */
#include <stdio.h>
#include "foo.h"
#include "bar.h"
int main (void)
{
printf ("foo() = %d\n", foo());
printf ("bar() = %d\n", bar());
return 0;
}
Now, if I make any changes to foo.c, all I have to do is recompile
that one file and relink; I don't have to recompile bar.c and main.c.