UC3M

Telematic/Audiovisual Syst./Communication Syst. Engineering

Systems Architecture

September 2017 - January 2018

Chapter 1.  Structure of a C program

Nowadays, there exist multiple programming languages called high level, which are those that allow to write programs significantly different to the assembly code or machine language, which is the one used by the processor to execute all the programs. Java is an object-oriented language high level because programs are organized around a set of classes and objects. C, however, does not have any type of object, and the programs are simply organized as a set of functions, thus it is a procedural language.

Java is a language with a rich functionality, and although it shares a significant portion of this functionality with Java, the differences are greater than the similarities. The code structures in C are much simpler that those in Java. In mechanisms such as loops, conditionals, etc, both languages are similar, but in the remaining aspects such as data structure definition, C offers simpler mechanisms.

1.1.  A C program

A C program is a set of functions, data type definitions and variable declarations contained in a set of files. A C program always start its execution by the function with name main. Any function can invoke any other function and the variables declared outside the function are either global or local to the current file (if they are declared with the static prefix). The following figure shows the structure of a C program contained in several files.

The C compiler is the program that translates a set of functions, definitions and declarations in multiple files into an executable file. The C compiler has a surprisingly simple behavior and performs much less work than expected when compared with others such as the Java compiler. To create an executable, the compiler processes the source files one by one independently. This means that the defined variables and functions are not remembered when processing another file. Furthermore, the compiler performs a single pass over the text, only those definitions up to the current compilation point are visible.

As a consequence of this behavior, a variable cannot be used unless it has been previously declared in the same file. Analogously, a function cannot be invoked unless its code has been previously included in the same file. To allow the division of code in multiple files the language allows the definition of function prototypes (the type of the result followed by the function name and the parameter types in parenthesis) without including the code, and also the definition of variables as external, that is, present in a different file. It follows an example of two files in which function fill_in and variable table are defined in one file but used inside in the main function.

File1.c File2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define SIZE 100
/* Array of 100 integers (Global)*/
int table[SIZE];

/* Fills an array with zeros */
void fill_in(int *t, int size) 
{
    int i;
    for (i = 0; i < size; i++) 
    {
        t[i] = 0;
    }
    return;
}
1
2
3
4
5
6
7
8
9
10
11
12
#define SIZE 100
/* Global variable declared in other file */
extern int table[SIZE];

/* Function declared in other file */
void fill_in(int *, int);

/* Program entry point */
int main(int argc, char *argv[]) {
    fill_in(table, SIZE);
    return 0;
}

Line 3 in File2.c notifies the compiler that there exist an array of 100 integers with name table defined in another file. Line 6 is a function prototype. It contains the result type (void) followed by the function name (fill_in) and the type and name of the parameters in parenthesis (int *t, int size). This line informs the compiler that a function with this definition is in a different location in the program. Thanks to this definitions, Line 11 is correct. The function fill_in can be invoked, and the variable table is known.

Line 1 of both files (#define) corresponds to a preprocessor directive, which tells the preprocessor to replace every occurrence of a particular character string (in this case, SIZE) with a specified value (in this case, 100). The C preprocessor runs before the compiler and is in charge of these replacements. Use the #define directive when you have to define constants in your program, especially for size arrays. Write these constants in upper case always, in order to be easily readable.

Answer the following questions to see if you understood what the content of this document:

  1. A C program is a set of definitions of three types: variables, functions and data types.

    • True

    • False

  2. Some functions and variables can be grouped in classes as in Java.

    • True

    • False

  3. I can use a function and then define it (include its code) in a place further down the same file.

    • True

    • False

  4. Because a function cannot invoke a function not defined previously, in C two functions that call each other cannot be written.

    • True

    • False

  5. What is a function prototype?

    • A line in the program containing its name.

    • A code line with the function name, parameters and the result it returns.

    • The function definition: name and parameters followed by the code.

    • A description written in paper of what a function should do in order to be implemented later.