One of the the best lessons to learn from sports is the need to continually practice the basics. In any sport or profession you should spend time reviewing the basics to ensure that your skills are sharp. Everything else builds off of the basics.
At this time I am in the process of reviewing the basics with the C programming language. From this language we get C++, Objective-C, Java, JavaScript and C# (pronounced C-sharp). C is a very important basic skill to practice as so many languages build off of the success of C.
Additionally, this language continues to change with the last standard having been defined in 1999 and a new standard began to be developed in 2007.
Since we are discussing the basics of C let’s begin with functions and declaration statements.
C Prototypes & Functions
Before a function can be called the compiler must understand how the function will be called. The prototype establishes a contract with the compiler defining how the function will be called.
The prototype must be defined in one of two places:
- In the .c file before the function is defined, or
- In the corresponding .h file which is called the header file (we’ll discuss this more in the next section about declaration statements).
The prototype has the form:
returnType functionName (parameterType parameterName1, parameterType parameterName2, ...);
The prototype must end with a semi-colon. It has the same syntax as the function except that the function has an opening and closing curly bracket:
returnType functionName (parameterType parameterName1, parameterType parameterName2, ...) { //Code Goes Here return returnTypeValue; }
A function that does not return a value is defined with a return type of void.
Pretty simple actually.
Declaration Statements
In C there are several declaration statements. A declaration statement provides pre-processing instructions to the compiler that tells the compiler how to link the code together and perform any other configuration changes necessary to complete the build.
For today’s post we’ll limit our discussion to the include declaration statement. The include statement tells the compiler where to find the header files that contain the routines needed by the current module.
As mentioned in the previous section a header file stores a set of declarative function statements called prototypes. Prototypes define the interface supported by the class file. Each header file has one .c file (although a .c file may exist without a header file).
The header file defines the contract for the modules that will consume or use the .c file associated with the header file. This is an early and rudimentary version of what is called an interface in object-oriented terms and may very well be the inspiration for the interface model.
To review…The include statements tell the compiler where to find the header file which tells the compiler the accepted contract for communicating with the functions in the .c file. Clear as mud? Good 🙂
There are two flavors of an include file:
- Standard C Library Reference, and
- Local, custom C reference.
The standard input output file is used heavily in common console or terminal applications. To reference the C Library file the name is enclosed with the less than and greater than characters.
#include <stdio.h>
On the other hand if we have a function in another C class we’ll need to reference the corresponding h (or header) file. This file will be in the same path as the other C file and thus will need to be reference with an include statement using opening and closing quotation marks.
#include "moduleName.h"
Calling a Routine in an External C File
To demonstrate calling a function contained in another .c file we’ll make a simple command console (or terminal) application. First thing to understand is that every C program has a Main routine. From this Main routine we’ll reference the header file that corresponds to the .c file containing the function we want to call.
#include "HelloWorld.h" int main (int argc, const char * argv[]) { char name[25]; GetName(name); name[24] = 0; DisplayName(name); return 0; }
For now don’t worry about the main parameters or return type. We’ll discuss that in a later post. Simply note that the include declaration is the first command as it must be listed in the code before any attempt to call the routine in the external .c file.
First we create a string variable that holds twenty five characters. Actually, in C a string is an array of char types.
Next we make a call to the GetName function in the external HelloWorld.c file. The next line ensures that a buffer overrun does not occur by forcing the last character to be a whitespace character.
Finally another function call is made to the external file to display the name.
I’m doing things a little out of sequence. Technically we should begin by creating the header file. However, to simplify the explanation of the code we started with the Main function.
Create the header file and add the parameters for the new HelloWorld.c file in the corresponding HelloWorld.h file.
void GetName(char *name); void DisplayName(char *name);
In the header file there are two functions both with a single parameter. The star prior to the parameter name indicates that the parameter is a pointer to the memory address of the variable. By using a pointer we reduce the amount of memory used and the amount of time to execute the function as the argument value does not have to be copied to the function parameter.
And, now for the C code in the HelloWorld.c file.
#include <stdio.h> void GetName(char *name) { printf("Enter Name: "); //The following line only reads 24 characters so that the 25th //can be guaranteed to be a whitespace character ensuring that //a buffer overflow is avoided. fgets(name, 25, stdin); } void DisplayName(char *name) { printf("Hello, %s\n", name); }
The printf function instructs the system to print the specified text value to the screen. The scanf function accepts input parameters until a whitespace character like the carriage return is entered. Both of these functions come from the Standard Input/Output C Library file, stdio.h.
Summary
In today’s post we learned how to create our own functions in external files, use the include directive to reference standard C library files and reference the external C code. In the process we demonstrated how to avoid buffer overflows and pass variables by reference using pointers.
Leave a Reply