Home CPSC 425

C Programming

 

Overview

C was designed in the early 70s as a language in which to develop the UNIX operating system. C was initially developed as a "portable assembly language", which gives programmers access to hardware in a general way.

C is still one of the most popular programming languages. It is also the basis for derived languages such as C++, Java, C#, Objective-C, PHP and Javascript.

C is used today mostly for system development. The Linux, Windows, and OSX operating system kernels are written in C. Many languages are implemented in C including the JVM, Python, Ruby, PHP, R. Extensions to these languages can also be written in C. C is also used for embedded systems.


 

Similarities with Java

Because C++ is a derivative of C, and Java is a derivative of C++, there are many things in common between C and Java:


 

Differences from Java


 

Hello World

The following is a C program which prints out a hello world message:


#include <stdio.h>

int main() {
    printf("Hello World!\n");
    return 0;
}

The #include statement is similar to an "import" in Java. We need that to be able to use standard input and output functions, including printf.

Like Java, C programs begin with a main function. However, main is not part of any class, needs not take any arguments, and returns an integer.

printf takes a string argument and prints it out to the screen.


 

Output

printf can be used to print multiple types of data. To do this, the first argument - which is always a string - must indicate which types of data will be printed in subsequent arguments.

The following example prints an integer and a double:


#include <stdio.h>

int main() {
    int number1 = 7;
    double number2 = 23.5;

    printf("Number1 = %d, Number2 = %lf\n", number1, number2);
    return 0;
}

The %d and %lf are format specifiers which indicate that the subsequent arguments after the first one should be substituted at that position. There are different specifiers for each built in type:

SpecifierType
%dint
%ldlong
%ffloat
%lfdouble
%cchar
%sstring
%ppointer

 

Functions and Control

Functions and control structures work basically the same as in Java, with the exception that functions are never part of a class. The following program prints out a table of factorials:


#include <stdio.h>

#define N 10

/* calculates a factorial recursively */
int fact(int x) {
    if (x == 0) {
        return 1;
    } else {
        return x * fact(x - 1);
    }
}

/* main function */
int main() {
    int i;

    for (i = 0; i <= N; i++) {
        printf("%d! = %d\n", i, fact(i));
    }

    return 0;
}

Notice that constants are created in C using a "#define" statement.

Also notice that the i variable is not declared inside of the for loop statement. This is not allowed in C89 which is the default version used by gcc. In C99, this is allowed.


 

Pointers

In C it is often necessary to deal with pointers which are variables which hold memory addresses. Like all variables, pointers must be declared. To declare a pointer, we give the type of memory the pointer holds, and a * character. To declare a pointer to an int:


int* pointer;

This variable does not store an integer, it stores the memory address of an integer. To get the address of something in C, use the & address operator.

The following program puts the address of an integer into a pointer, and prints both out:


#include <stdio.h>

int main() {
    int x = 42;
    int* pointer = &x;

    printf("x = %d, pointer = %p\n", x, pointer);

    return 0;
}

Note that the %p is used to print pointers. This will print 42 as the value of x, and some large number as the value of pointer. The actual number is not important, and will change in each execution.

We can use pointers to access the variables that they point to by dereferencing the pointer. This is done with the * operator. The following program uses this to access, and then to change, the value of x:


#include <stdio.h>

int main() {
    int x = 42;
    int* pointer = &x;

    /* print x through the pointer */
    printf("x = %d\n", *pointer);

    /* change x through pointer */
    *pointer = 100;

    /* see that x has changed */
    printf("x = %d\n", x);

    return 0;
}

 

Input

Input in C can be done with the scanf function. Like printf, scanf takes a string as its first argument which indicates which type(s) will be read. We then pass a pointer to the variable which scanf should store the input in.

For example, this program reads a number from the user:


#include <stdio.h>

int main() {
    int x;

    printf("Enter a number: ");
    scanf("%d", &x);

    printf("You entered %d.\n", x);

    return 0;
}

scanf takes a pointer to a memory location, and writes the data the user enters at that location. When we pass the address of x, scanf will write the input into the variable x.

scanf can also read multiple pieces of input at once, possibly with other text in between. For example, the following reads a date formatted as M/D/Y:


#include <stdio.h>

int main() {
    int m, d, y;

    printf("Enter a date: ");
    scanf("%d/%d/%d", &m, &d, &y);

    printf("You entered %d/%d/%d\n", m, d, y);

    return 0;
}

When the input does not match the expected form, scanf will return and not fill values into the variables given. scanf also returns the number of values that it successfully read.


 

Arrays

Arrays in C are more basic than they are in Java. They are not objects, and don't know what their size is. An array is simply a block of memory holding a certain number of variables.

The following program shows how arrays can be used:


#include <stdio.h>

#define SIZE 5

int main() {
    int array[SIZE];

    int i;
    for (i = 0; i < SIZE; i++) {
        array[i] = i * SIZE;
    }

    for (i = 0; i < SIZE; i++) {
        printf("%d\n", array[i]);
    }

    return 0;
}

Array names are essentially just pointers to the start of memory where the array is stored. For that reason, we can also loop through an array using pointer syntax:


int* ptr;
for (ptr = array; ptr < (array + SIZE); ptr++) {
    printf("%d\n", *ptr);
}

When passing an array to a function, we also pass it as a pointer:


#include <stdio.h>

#define SIZE 5

int sum_array(int* array, int size) {
    int sum = 0, i;

    for (i = 0; i < size; i++) {
        sum += array[i];
    }

    return sum;
}

int main() {
    int array[SIZE];

    int i;
    for (i = 0; i < SIZE; i++) {
        array[i] = i * SIZE;
    }

    int sum = sum_array(array, SIZE);
    printf("The sum is %d\n", sum);

    return 0;
}

 

Strings

C has no built in string type, strings are just arrays of characters. Because arrays do not give any way to get their size, the convention in C is that the end of a string is marked by a "NULL terminator" at the end. To store the word "hello", you need an array of size six!

Below shows how the string "Hello World!" would be stored in an array of characters:

The following program demonstrates declaring, printing and reading strings:


#include <stdio.h>

int main() {
    /* declare a string of up to 30 characters (one needed for NULL) */
    char name [31];

    /* initialize a string - the compiler automatically gives
     * enough space for the characters and NULL terminator */
    char str [] = "Hello world!";

    /* print a string */
    printf("%s\n", str);

    /* read a string */
    printf("Enter your name: ");
    scanf("%s", name);

    return 0;
}

The <string.h> library includes several functions for dealing with strings. Some of the most useful are listed below:

FunctionMeaning
strlen(str)Returns the length of the string it is given.
strcpy(str1, str2)Copies the contents of str2 into str1.
strcat(str1, str2)Concatenates str2 to the end of str1.
strcmp(str1, str2)Compares str1 and str2 for equality. It returns less than 0 if str1 is less than str2, 0 if the strings are equal, and greater than 0 if str1 is greater than str2.

Copyright © 2024 Ian Finlayson | Licensed under a Attribution-NonCommercial 4.0 International License.