A .o file contains the following:
	a) It contains the machine code for the .c file
	b) It is possible that not all the functions used by the .c file are defined in the .o file
	   Some of them might be defined externally as in the case of main.c. The function "factorial"
 	   was defined in the file factorial.c . Hence, a .o file needs to keep a table of the functions
       and variables that are possibly defined in other .o files.
   c) What was the last step of compilation? 
	   We combined main.o and factorial.o to make an a.out file

      We had kept an entry in the main.o file that the function factorial was defined externally.
      When we linked the two .o files, the linker was able to find the definition of the function "factorial"
      It then updated the machine code stored in the main.o file to point to the right location of the
      function. 

Linking is the last stage of compilation. 
< This is called Static Linking >
What does it do ? It combines multiple .o files to make an a.out file.
How does it achieve that ? 
(1)	  It takes all the text sections (machine code) of all the .o file, and creates
 one large text section. 
(2) It searches for all the unresolved functions (e.g. factorial in file main.o)
    For each unresolved function, it finds the definition in other .o files.
(3) Once it finds a definition, it finds the address of the function and patches
    the original machine code. 
(4) It adds some more meta information (packaging information) , it creates the final
binary. 

Disadvantages of static linking: 
	(1) Code of the function is now a part of the binary. If I want to change it later, I cannot without
 recompiling the binary. 

dll file (dynamically linked library)
(1) The code of a function is not a part of the binary. 
(2) We just create a stub for the factorial (or puts or printf or scanf) function. 
stub --> dummy function
(3) When you call printf/puts for the first time
	(a) The stub is called. The stub goes and locates the .so (shared object, linux version of dll) file.
   It finds the function printf/puts inside the .so file, and loads the code for it.
(4) We are at will to change the implementation of printf.
(5) I need not be using all the functions all the time. A dll allows me to load only those
functions that I require.






