Hostingheaderbarlogoj
Join InMotion Hosting for $3.49/mo & get a year on Tuts+ FREE (worth $180). Start today.
Advertisement

Learning C: A Primer

by
Gift

Want a free year on Tuts+ (worth $180)? Start an InMotion Hosting plan for $3.49/mo.

This post is part of a series called Learn iOS SDK Development From Scratch.
Creating Your First iOS Application
Getting Started with Objective-C

You may have heard that you need to be familiar with Objective-C if you plan to develop iOS applications. While Objective-C is indeed an important component of iOS development, people tend to forget that Objective-C is a strict superset of C. In other words, it is also important to be familiar with the fundamentals of C as an iOS developer. Don't worry though. If you already know the basics of programming, C will not be too difficult to pick up.

Prerequisites

It is not possible to cover the basics of programming and learn C in one article. I am therefore assuming that you already have some programming experience. Ruby, PHP, or JavaScript are good starting points for learning C and Objective-C, so if you come from a web development background you shouldn't have problems learning the basics of C by reading this article.

In this article, I will focus on what makes C unique or different from other programming languages. This means that I won't cover basic programming concepts and patterns, such as variables and loops. What I will cover is how variables are declared in C and what pointers are. In other words, the focus lies on the things you need to know to become familiar with C.

Introduction

Dennis Ritchie started developing C in the late 1960's while working at AT&T Bell Labs. Thanks to its widespread use and simplicity of design, C can be used on almost any platform. It is not tied to any one operating system or platform. If you have explored other programming languages, then you might have noticed that they share a lot of similarities. Many languages have been inspired by C, such as C#, Java, PHP, and Python.

Dennis Ritchie named his new language C because he took some inspiration from a prior language developed by Ken Thompson called B. Despite the fact that C is inspired by typeless languages (Martin Richards's BCPL and Ken Thompson's B), C is a typed language. I will cover typing in more detail later in this article.

It doesn't take long to learn the basics of C, because it is a fairly small language with only a small set of keywords. You could say that C is very bare bones and only offers what is really necessary. Other functionality, such as input/output operations are delegated to libraries. Heap and garbage collection are absent in C and only a basic form of modularity is possible. However, the small size of the language has the benefit that it can be learned quickly.

Despite the fact that C is a low level language, it is not difficult to learn or use. Many iOS and Mac developers have become so used to Objective-C and its object oriented design that they are afraid to try working with "straight" C or C libraries. Objective-C is a strict superset of C and nothing more than a layer on top of C.

Practice Makes Perfect

A programming language is best learned by practicing, so let's create a new project in Xcode and write a few lines of C to get to know the language. Launch Xcode and create a new project by selecting New > Project... from the File menu.

Learning C A Primer - Creating a New Xcode Project - Figure 1

We won't be creating an iOS application like we did earlier in this series. Instead, we will create an OS X project. Select Application in the section labeled OS X and choose Command Line Tool form the list of templates on the right. Click the Next button to continue.

Learning C A Primer - Choosing the Command Line Tool Template - Figure 2

Name your project C Primer and give it an organization name and company identifier as we saw previously. Set the Type drop down menu to C. The only configuration option that really matters for this tutorial is the type. Don't worry about the other options for now. Click the Next button to continue.

Learning C A Primer - Configuring the Project - Figure 3

Tell Xcode where you want to save the new Xcode project. It isn't necessary to create a git repository for this project. We will only be using this project for learning C instead of creating a useful command line tool.

Learning C A Primer - Specifying a Location to Save the Project - Figure 4

Project Overview

In comparison with the iOS application that we created earlier in this series, this project is surprisingly minimal. In fact, it only contains two source files, main.c and C_Primer.1. For the purposes of learning C, only main.c is of interest to us. The file's extension, .c, indicates that it is a C source file.

Learning C A Primer - An Overview of the Project - Figure 5

Before we build and run the command line tool, let's take a look at the contents of main.c. Apart from a few comments at the top of the file and a function named main at the bottom, the source file doesn't contain much. The file also contains an include statement that I will talk about more a bit later in this article.

//
//  main.c
//  C Primer
//
//  Created by Bart Jacobs on 15/02/14.
//  Copyright (c) 2014 Tuts+. All rights reserved.
//

#include <stdio.h>

int main(int argc, const char * argv[])
{

    // insert code here...
    printf("Hello, World!\n");
    return 0;
}

A closer look at the main function reveals a few interesting characteristics of the C programming language. I mentioned earlier that C is a typed language, which means that variables as well as functions are typed. The implementation of the main function starts by specifying the return type of the function, an int. Also note that the arguments of the function are typed. The keyword function, which is common in many other languages, is absent in C.

The body of the main function starts with a comment (single line comments start with //). The second line of the function's body is another function, which is part of the C standard library, hence the #include statement at the top of the file. The printf function sends output to the standard output, "Hello, World!\n", in this case. The \n specifies a new line. In Xcode, however, the output is redirected to the Xcode Console, which I will talk about more in a bit.

The main function ends by returning 0. When a program returns 0, it means that it terminated successfully. That is all that happens in the main function. Don't mind the arguments of the main function as this is beyond the scope of this tutorial.

Build and Run

Now that we know what the main function does, it is time to build and run the command line tool. By building the application, the code in main.c is compiled into a binary, which is then executed. Build and run the command line tool by clicking the triangular play button at the top left of the window.

If all went well, Xcode should show the debug area at the bottom of the window. You can show and hide the debug area by clicking the middle button of the View control in the toolbar at the top right.

Learning C A Primer - How to Show and Hide the Debug Area in Xcode - Figure 6

The debug area has two sections. On the left is the Variables window and on the right is the Console window. In the Console, you should see the words Hello, World!. Xcode also tells you that the program ended with exit code 0, which means that the program ended normally.

Learning C A Primer - The Project Window with the Debug Area Visible - Figure 7

In a Nutshell

In the rest of this article, I will cover the most important characteristics of C. What is covered in this tutorial is limited to what you need to know to get started with iOS development. In the next article of this series, I will cover Objective-C.

In contrast to interpreted languages, such as Ruby, PHP, and JavaScript, C is a compiled language. The source code of a program written in a compiled language is first compiled into a binary that is specific to the machine it was compiled on. The compilation process reduces the source code to instructions that can be understood by the machine it runs on. This also means that an application compiled on one machine is not guaranteed to run on another machine.

It goes without saying that programs written in interpreted languages also need to be reduced to instructions that the target machine can understand. This process, however, takes place during runtime. The result is that, generally speaking, programs written in a compiled language are faster when executed than those written in an interpreted language.

Data Types

Another important difference with languages like PHP, Ruby, and JavaScript is that C is a typed language. What this means is that the data type a variable can hold needs to be explicitly specified. In C, the fundamental data types are characters (char), integers (int), and floating-point numbers (float). From these fundamental types, a number of additional types are derived, such as double (double precision floating-point number), long (integer that can contain larger values), and unsigned (integer that can only contain positive values and therefore larger values). For a complete list of the basic C data types, I recommend taking a look at the Wikipedia page about C data types.

Have you noticed that strings weren't mentioned in the list of basic C data types? A C string is stored as an array of chars. A char can store one ASCII character, which means that an array of chars can store a string. Take a look at the following example to see what this means in practice. The square brackets immediately after the variable name indicate that we are dealing with an array of chars. A C string is zero terminated, which means that the last character is 0.

char firstName[] = "Bart";

Let's explore typing in more detail by comparing two code snippets. The first code snippet is written in JavaScript, whereas the second snippet is written in C. In JavaScript, a variable is generally declared with the var keyword. C doesn't have a keyword to declare variables. Instead, a variable in C is declared by prefixing the variable with a data type, such as int or char.

var a = 5;
var b = 13.456;
var c = 'a';
int a = 5;
float b = 13.456;
char c = 'a';

Let's introduce some variables in the main function that we saw earlier. Change the body of the main function to look like the code snippet below. To print the variables using the printf function, we use format specifiers. For a more complete list of available format specifiers, visit this link.

int main(int argc, const char * argv[])
{

    // insert code here...
    printf("Hello, World!\n");

    // Variables
    int a = 5;
    float b = 6.3;
    char c = 'r';

    printf("this is an int: %i\n", a);
    printf("this is a float: %f\n", b);
    printf("this is a char: %c\n", c);

    return 0;
}

As we saw earlier, in C, typing isn't limited to variables. Functions also need to specify the type they return as well as the type of the arguments they accept. Let's see how this works.

Functions

I am assuming that you are already familiar with functions. As in other languages, a C function is a block of code that performs a specific task. Let's make main.c more interesting by introducing a function. Before the main function, we added a function prototype. It tells the compiler about the function, what type it returns, and what arguments it accepts. At the bottom of main.c, we insert the implementation of the function. All the function does is multiply the argument that is passed to the function by five and return the result.

#include <stdio.h>

int multiplyByFive(int a); // Function Prototype

int main(int argc, const char * argv[])
{

    // insert code here...
    printf("Hello, World!\n");

    // Variables
    int a = 5;
    float b = 6.3;
    char c = 'r';

    printf("this is an int > %i\n", a);
    printf("this is a float > %f\n", b);
    printf("this is a char > %c\n", c);

    // Functions
    printf("Five multiplied by five is %i\n", multiplyByFive(5));

    return 0;
}

int multiplyByFive(int a) {
    return a * 5;
}

We've also updated the main function by invoking the multiplyByFive function. Note that a function prototype is not strictly necessary on the condition that the implementation of the function is placed before it is called for the first time. However, using function prototypes is useful as it allows developers to spread source code over multiple files and thereby keeping a project organized.

If a function doesn't return a value, then the return type is declared as void. In essence, this means that no value is returned by the function. Take a look at the following example. Note that the function doesn't accept any arguments. The parentheses after a function's name are required even if the function doesn't accept any arguments.

// Function Prototype
void helloWorld();

// Function Implementation
void helloWorld() {
  printf("Hello, World!\n");
}

Before we move on, I want to mention that the C language doesn't have a function keyword for declaring a function like in JavaScript or PHP. The parentheses after the function name indicate that helloWorld is a function. The same is true for variables as I mentioned earlier. By prefixing a variable name with a type, the compiler knows that a variable is being declared.

You may be wondering what the benefits are of a typed language, such as C. For programmers coming from Ruby or PHP, learning a typed language might be confusing at first. The main advantage of typing is that you are forced to be explicit about the behavior of the program. Catching errors at compile time is a major advantage as we will see later in this series. Even though C is a typed language, it is not a strongly typed language. Most C compilers provide implicit conversions (e.g., a char that is converted to an int).

Structures

What is a structure? Allow me to quote Kernighan and Ritchie. A structure is a collection of one or more variables, possibly of different types, grouped together under a single name for convenient handling. Let's look at an example to see how structures work. Add the following code snippet right before the main function's return statement.

// Structures
struct Album {
    int year;
    int tracks;
};

struct Album myAlbum;
struct Album yourAlbum;

myAlbum.year = 1998;
myAlbum.tracks = 20;
yourAlbum.year = 2001;
yourAlbum.tracks = 18;

printf("My album was released in %i and had %i tracks.\n", myAlbum.year, myAlbum.tracks);
printf("Your album was released in %i and had %i tracks.\n", yourAlbum.year, yourAlbum.tracks);

We start by declaring a new structure type and we give it a name of Album. After declaring the new type, we use it by specifying that the variable we are about to declare is a struct and we specify the struct's name, Album. The dot-notation is used to assign values to and read the values from the variables the struct holds.

Pointers

Pointers are often a bit of a stumbling block for people who want to learn C. The definition of a pointer is very simple though. A pointer is a variable that contains a memory address. Keep in mind that a pointer is just another C data type. Pointers are best understood with an example. Paste the following code immediately before the return statement of the main function.

// Pointers
int d = 5;
int *e = &d;

printf("d has a value of %i\n", d);
printf("e has a value of %p\n", e);
printf("the object that e points to has a value of %i\n", *e);

We start by declaring an int and assigning a value to it. In the following line, we declare a pointer to int named e by prefixing the variable name with an asterisk. The ampersand before the variable d is a unary operator (a fancy name for an operator that has one operand) that is know as the address-of operator. In other words, by prefixing the variable d with an ampersand, our pointer e is given not the value of d, but the address in memory where the value of d is stored. Remember the definition of a pointer, it is a variable that contains the address of a variable.

The print statements after the variable declarations will make this example clearer. Build and run the example and inspect the output in the console. The value of d is 5 as we expect. The second print statement might surprise you. The pointer named e contains a memory address, the place in memory where the value of d is stored. In the final statement, we use another unary operator, the dereferencing or indirection operator. What this operator does, is accessing the object that is stored at the location the pointer is pointing to. In other words, by using the dereferencing operator we retrieve the value of d.

Remember, when a variable is declared in the C programming language, a block of memory is allocated for that variable. A pointer simply points to that block of memory. In other words, it holds a reference to the variable that is stored in the block of memory. Make sure that you understand the concept of pointers before moving on to the next article in which we take a look at Objective-C. Pointers are used all the time when working with objects.

Don't worry if pointers don't immediately make sense after reading this article. It often takes some time to really grasp the concept. There is an excellent post written by Peter Hosey that I cannot recommend enough.

Mind the Semicolon

It seems as if semicolons are no longer hip. Ruby isn't fond of semicolons and the new cool kid in town, CoffeeScript, doesn't like them either. In C and Objective-C, semicolons are required at the end of every statement. The compiler is not very forgiving as you may have noticed.

Conclusion

There is more to the C programming language than what I've covered in this article. In the next article, however, I will talk about Objective-C and it will gradually improve your understanding of C. Once we start working with the iOS SDK, I'm sure you'll get the hang of working with objects and pointers in no time.

Advertisement