Broad Network


Including Files in the C Computer Language

Part 40 of the Complete C Course

Foreword: Including, Files, C, Computer, Language

By: Chrysanthus Date Published: 22 Jun 2024

Joining two Related Files

A long file can be split into two, and then the top half, fitted at the top of the lower-half. This inclusion is done using the preprocessing directive, #include. Consider the following program:

    #include <stdio.h>
    
    #define anInt 44
    int it = 66;

    int myFn(int inte)
        {
            return inte;
        }

    int main(int argc, char *argv[])
        {
            int ret1 = myFn(anInt);
            int ret2 = myFn(it);
            printf("%i %i\n", ret1, ret2);
        
            return 0;
        }

The output is 44 66. Notice that there are two preprocessing directives in the program: "#include <stdio.h>" and "#define anInt 44". Note that the preprocessing directives do not end with semicolons; as they should not. To compile this file, the user will type at the command prompt:

    gcc -o program.exe file.c

and press Enter, where "program.exe" is the name of the binary file (executable), given by the programmer, and "file.c" is the name of the source (text) file, also given by the programmer. The executable file would be run as:

     ./program.exe

pressing Enter after typing the command.

The program can be split into two halves: The C main() function definition, becomes the bottom half and the rest of the code above becomes the top half. The bottom half is saved with the name, first.c, for first file that has the main() function. The top half is saved as second.c . The only additional code in the first file to enable both files work together, would be

    #include "second.c"

So the content of the lower half becomes:

    #include "second.c"

    int main(int argc, char *argv[])
        {
            int ret1 = myFn(anInt);
            int ret2 = myFn(it);
            printf("%i %i\n", ret1, ret2);
        
            return 0;
        }

The top half remains unchanged, as follows:

    #include <stdio.h>
    
    #define anInt 44
    int it = 66;

    int myFn(int inte)
        {
            return inte;
        }

When does the programmer use the angle brackets, <> with the #include directive, and when does he/she use the double quotes, "". The angle brackets are used with files that come with the compiler installation. Double quotes, "" are used with user (programmer) created files. The files, first.c and second.c are saved in the same directory (the user's home directory). To compile the files into one program, the user will type at the command prompt,

    gcc -o program.exe first.c

The result is the same as with the un-separated file. The #include directive, has included the whole of its argument file, into the position, where it was typed. So, second.c did not have to be quoted in the command line.

Prototype

A prototype in C, is the function signature (including the return type), ending with a semicolon. This is a declaration and not a definition. The prototype and its function definition can exist in the same single program file, like so:

    int myFn(int inte);
    
    int myFn(int inte)
        {
            return inte;
        }

Header File

An application consists of more than one file. In C, only one of these files has the main() function. There is a limit to overall file size in C, to which almost complete files can be included at the top of one another, going up. In other words, there is a limit to the total length of a source file. Seen another way, there is a maximum length of the overall source file. An application in C, should be seen as a broad set of files (wide), rather than as a long set of files (tall). This is done using header files. There is also a limit to the length of each separate file, in an application. An application can still consist of files at this limit. However, this is only possible with header files.

A header file has prototypes for functions, and not the function definitions themselves. The function definitions are found in the different normal files, or in a library. A function is defined only once. The same function is not defined in different files. The header file may have as well, a few fundamental object declarations, such as for int, and float objects. It typically has function prototypes. It is these header features that link the different source files.

So, a header file has prototypes. It may have a few fundamental object declarations, with or without the associated definitions (initialized values). Today, a header file may also have struct and union declarations, without definitions, because definitions occupy more space. Each definition of a struct or union will be codded only once. The definition will be coded only in one of all the files, or in a library.

Now, in the application with all the files combined, the header is included in each file that needs the body of the function or struct or fundamental initialization; this also concerns the file with the C main() function. There are usually more than one header file; not necessarily all included in all files. So, it is the header files that connect the files in a C application. Avoid including full and related files at the top of one another. Use headers, to combine files.

A header file for the above first.c and second.c files would be:

    #define anInt 44
    int myFn(int inte);

This file can be created and saved as "head.h". The first.c file would have the content,

    #include <stdio.h>
    #include "head.h"

    int main(int argc, char *argv[])
        {
            int it = 66;
        
            int ret1 = myFn(anInt);
            int ret2 = myFn(it);
            printf("%i %i\n", ret1, ret2);
        
            return 0;
        }

The reason why "int it = 66;" has been brought into the C main() function, will be explained shortly. The second.c file would have the content,

    #include <stdio.h>
    #include "head.h"

    int myFn(int inte)
        {
            return inte;
        }

Both the first.c and the second.c files include two header files. They do not include full related files. stdio.h is in angle brackets, because it comes with the big C library. The big C library consists of sub (or smaller) libraries, like the stdio and stdlib libraries. The files that form the application, will be compiled as follows:

    gcc -o app.exe first.c second.c

The executable file is called app.exe. Although it is finally a long file, see it as a broad file. The two files, first.c and second.c are in the command line. Press Enter after typing. Note that the header files, stdio.h or head.h are not in the command line. This is because they have already been included in the two files. The output, when app.exe is executed (run), will be the same: 44 66. The application (broad program), would be run (executed) at the command line, with:

    ./app.exe

The reader should test all the above code, as they are related.

The extern Reserved Word

In the past, declarations of fundamental objects, were done using the #define preprocessing directive, for multiple files that form an application. It is not very convenient, to use the #define preprocessing directive. It is better to use a conventional declaration, like "int inte = 66;" in the header file, and precede it with the reserved word, "extern", without the quotes. Such a variable associated with it (e.g. inte above) is a true global variable, in C++, which is a supper-set language of C. So, "int it = 66;" for example, can be removed from a function, and put into a header file as follows:

        extern int it;

A header file content can be,

    #define anInt 44
    extern int it;
    int myFn(int inte);
    extern struct Accountants {char *name; int age; float salary; char *HQ;} employee1;

The extern reserved word, does not allow initialization. Each separate file then has the responsibility to re-declare the same variable, with initialization. The extern struct declaration has just been included above, for completeness of an application example. Its identifier of interest, is employee1, and not Accountants. The content of a first.c file would be:

    #include <stdio.h>
    #include "head.h"
    
    int it = 66;

    int main(int argc, char *argv[])
        {        
            int ret1 = myFn(anInt);
            int ret2 = myFn(it);
            printf("%i %i\n", ret1, ret2);
        
            return 0;
        }

The variable "it", has been re-declared in the file scope of the first.c file. Since the extern reserved word, does not allow initialization, the #define preprocessing directive, still has a place in today's C programming. It is typically used, as constants, today.

Recall: extern is a storage-class specifier. The content of second.c file would become,

    #include "head.h"
    
    struct Accountants employee1;

    int myFn(int inte)
        {
            employee1.name = "John Smith";
            employee1.age = 30;
            employee1.salary = 1234.12;
            employee1.HQ = "Msc";
        
            return inte;
        }

It is left as an exercise for the reader, to save the new first.c and new second.c; then compile and run.



Related Links

More Related Links

Cousins

BACK NEXT

Comments