Larger Programs

Multi-File Programs

Multi-File Example

Recall this function to find the average of two numbers:
float average(float a, float b)
{
  return (a + b) / 2;
}
And we want to use it in our program. This is main.c:

#include <stdio.h> /* printf */

int main(void)
{
  float ave = average(4.0F, 5.0F);
  
  printf("The average is %.2f\n", ave);

  return 0;
}
Of course, this is going to cause problems:
gcc -Wall -Wextra -ansi -pedantic main.c
We have a warning from the compiler and an error from the linker:
main.c: In function `main':
main.c:5: warning: implicit declaration of function `average'
/cygdrive/h/temp/ccQga4Es.o:main.c:(.text+0x3e): undefined reference to `_average'
collect2: ld returned 1 exit status
We can fix the compiler warning by simply providing a prototype (declaration) for average:
#include <stdio.h> /* printf */

/* Function prototype */
float average(float x, float y);

int main(void)
{
  float ave = average(4.0F, 5.0F);

  printf("The average is %.2f\n", ave);

  return 0;
}
Of course, this still causes the linker to complain:
/cygdrive/h/temp/ccCYTR0j.o:main.c:(.text+0x3c): undefined reference to `_average'
collect2: ld returned 1 exit status
We need to tell the linker where to find the function average. First, we need to compile the code that contains the function average. Assume this is in average.c
float average(float a, float b)
{
  return (a + b) / 2;
}
Compiling it: (Note the -c switch which will compile the file, but not link. THIS IS IMPORTANT.)
gcc -Wall -Wextra -ansi -pedantic -c average.c
Had we not used the -c switch, we would have encountered this fatal error:
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../libcygwin.a(libcmain.o):(.text+0xab): undefined reference to `_WinMain@16'
collect2: ld returned 1 exit status
The linker is telling us that it can't find a function called main. This makes sense, since average.c doesn't contain a main function and all programs need a main function.

We just need to make sure that we perform all of the steps:

gcc -Wall -Wextra -ansi -pedantic -c main.c -o main.o       <--- compile main.c to main.o
gcc -Wall -Wextra -ansi -pedantic -c average.c -o average.o <--- compile average.c to average.o
gcc main.o average.o -o program.exe                         <--- link main.o and average.o to program.exe
And we can do this in one step: (Compile both C files and link them together to form an executable program.)
gcc -Wall -Wextra -ansi -pedantic main.c average.c -o program.exe
We can see see the files on the disk and their relative sizes:
9/17/2015  08:35a        62 average.c
9/17/2015  08:56a       209 main.c	
9/17/2015  09:15a       458 average.o
9/17/2015  09:15a       650 main.o
9/17/2015  09:14a     9,089 program.exe