Skip to content
ajd98 edited this page Apr 9, 2018 · 4 revisions

Exercise 0: Basics of C and Make

Let's examine the source code for a basic C program. Start by cloning the repository associated with this wiki.

git clone https://github.com/ajd98/c_tutorial.git

Enter the cloned repository and navigate to the ex0 subdirectory. Enter the following example into a file named helloworld.c; I recommend re-typing the file rather than copying with the system clipboard, so that you get used to typing the source code.

#include <stdio.h>

// Print "hello world!" to STDOUT (standard output)
int
main ()
{
  printf("Hello, world!\n");
}

This program simply prints the message "Hello, world!" to the terminal. We will go through the program line-by-line, as every part of the source code is important.

#include <stdio.h>

C programs typically use header files, which enable the programmer to use pre-defined functions and variables. For example, we would rather not write a program that specifies every individual pixel that should light up to display "Hello, world!" on the terminal, so we can use the stdio library, which provides the printf function. We don't need to write the printf function itself; we just need to include the relevant header file. While it is not totally comparable to Python's import statement, you could think of the #include statement in C and the import statement in Python as accomplishing similar tasks.

// Print "hello world!" to STDOUT (standard output)

The double slash // indicates a comment line. While not necessary as per C standards, it is good practice to include a comment before each function declaration. You can also write a multi-line comment as follows:

/*
 * This 
 * is 
 * a 
 * multi-line
 * comment
 */

Now, we get to the meat of the program:

int
main ()
{
  printf("Hello, world!\n");
}

This block of code defines the main function. Every C program has a main function, which is what is executed when you run the program. Every function in C has the following syntax:

DATATYPE
FUNCTION_NAME () 
{
  <code>
  ...
}

In general, DATATYPE can be one of a number of options such as int (an integer), float (a floating point decimal), char (a single character), and more. In the case of the main function, DATATYPE should always be int. It is good practice to write the function name on the line following the return type, as shown above. Following the function name, a pair of parenthesis must be included, and inside the parenthesis should be any arguments for the function; the main function has no arguments. Curly braces enclose the body of the function, and each line of code ends in a semicolon. Don't forget the semicolons when coding! This is one of the easiest mistakes to make, especially when coming from a language such as Python.

Compiling the program

To run the program, it must be compiled. This term is commonly used to encompass all the steps of translating your source code to instructions for your processor. In our case, compilation is simple. After saving the source file, run:

gcc helloworld.c -o helloworld

Then, type the following to run the program:

./helloworld

You should see "Hello, world!" printed to your terminal.

Compiling with Make

In larger projects, compilation can necessitate the use of many commands to separately compile source files and combine them to create a program. Rather than typing out all of these commands each time you wish to compile, a Makefile can be used instead. A Makefile, such as that already found in your ex0 directory, offers a series of rules for compiling files. These rules are of the form

<output file>:
	<command to create output file>

where the text and angle brackets are replaced with appropriate values. For example, we can write a rule for compiling helloworld from helloworld.c using the same command as we first used to compile helloworld:

helloworld:
	gcc helloworld.c -o helloworld

This rule says that to compile helloworld, the command gcc helloworld.c -o helloworld should be run. To use the rule, you can type make helloworld from the command line; make will automatically look through Makefile for a corresponding rule and execute the relevant command.

It is also worth noting that make aims to avoid unnecessary re-compilation of files. If the target file already exists and has a later time stamp than the source files, make will skip compilation of that target.

Clone this wiki locally