November 2nd, 2012, 09:05 PM
Defining, heading, and calling functions each from separate files?
I'm using Microsoft Visual Studio. I'm defining functions in one cpp file, calling the functions in another cpp file(this one includes the main() ), and writing the header(.h) for the functions in a separate file. In the cpp file where I define the functions, do I have to #include <stdio.h> to use printf statements, even if I've already included stdio.h in the main cpp file? If so, is there any way I can print out the results of the function without using printf?
November 2nd, 2012, 10:05 PM
Yes and yes.
Read up on the build process in C and also in C++. Every source file (.c and .cpp) is compiled separately as a separate entity. No source file knows automatically what exists in another source file nor does it know anything about what any of the other source files have done or will do. That information is provided by the header files (.h and .hpp).
So, first there's the pre-processor stage in which all the #include's are performed in which the entire file being included gets inserted into the source file at the location of the #include. And conditional compilation statements are used to determine which parts of the source file will be used and which will not. And macros are expanded. The result of the pre-processor stage is the actual source code that will be compiled. And remember that this is done separately and independently for each and every source file in the project.
Next comes the compilation stage in which the compiler starts at the top of the source file and translates it to object code -- now that is an understatement! The result is an object file which contains marked-up assembly/machine code that the source code translated to, plus information about what functions and global variables this file contains, plus information about what external functions and global variables this file depends on and expects to be found in another object file, plus information about where in the object code the place-holders are for the addresses of those externals -- those are called "unresolved addresses", implying that we want to resolve them, but that comes later. Now, it's the function prototypes and variable extern's in the header file that told the compiler what external functions and variables to expect.
In the overall build process, you do the pre-processor and compiler stage for each and every source file, so when you're done with all of the source files then you have a collection of object files and library files. The library files are either what were provided for you (eg, standard C/C++ libraries and third-party libraries) and are specialized object files.
So, now comes the linker stage. The linker reads the information in all the object and library files and builds tables of information about what all the functions and globals and where they are (ie, what address in which file each one has). Then it starts stringing the object files together and goes in and resolves all the unresolved addresses in the object code. And it links in other stuff that's needed, including libraries and start-up code and tables of information that's needed to execute that program. The product of the linker stage is an executable file.
That's the end of the build process, but there's more work to be done. All the resolved addresses in the executable file are offsets based on some starting address, but if you tried to copy that file into memory and run it, it would not work. All those address have to be fixed in memory. Think about it: when you build the executable you cannot possibly know exactly where in memory it will run. This address fixing is done by an operating system utility that in MS-DOS (where I learned about all this decades ago) was called the loader. The loader would acquire the system resources needed by the program (eg, a specific memory space), copy the executable in that memory location, and go through the executable code replacing all the address with their real locations in memory.
And that, in a very concise nutshell, is how that works. So then, yes, each and every source file that uses a particular external function (which includes standard library functions) must #include the header file that contains that function's prototype.
As for whether there are other ways of printing than printf, the answer is yes. But it depends on what you're doing. printf will not work in a GUI application, so for GUIs you have other functions to display a string. printf will only work for console apps and it will work for both C and C++, but C++ also has iostreams. In fact, since you're writing in C++, I'm very surprised that you could find any book or teacher who would even tell you about the existence of printf. FWIW, I very much prefer printf over iostreams.
Hope that helped.