Observera att detta är en arbetsversion av sidan!
Dölj style3dev.css för att bli av med annoteringarna!

Lesson 1: The very basics of C-programming

Purpose: Introduce the C programming language.
Contents: 1. Compile and run a C program.
2. Basic components of C programs.
References: C Programming in wikibooks and/or C tutorial in tutorialspoint.
Estimated time 15 min - 2 hours depending on your earlier experiences.

Before you start

The minimal requirements for programming in C are

  1. an editor which is used to enter and edit the program text and
  2. a C compiler which is used to translate the C-program to something the hardware can execute.

We recommend that you use the Linux computers at the IT-department for this lesson. That system has a couple of editors available like gedit, emacs, vi and vim. Choose whatever you like.

It is also possible to use an integrated environment like eclipse but it takes longer time get going unless you are already familiar with it.

It is of course also possible to use your own computer but you will probably have to install some software (e g xCode on a Mac and Cygwin or MinGW on a Windows system. See https://www.tutorialspoint.com/cprogramming/c_environment_setup.htm for instructions.

The first program

  1. Start your editor and enter the following code
    // A classic starter #include <stdio.h> int main() { printf("Hello world!\n"); return 0; }
    (This famous first program comes from "The C Programming Language" which is the standard textbook by Brian Kernighan and Dennis Ritchie published 1978. It has been widely used in many textbooks in most programming languages since then.)
  2. Save the program under the name hello.c.
  3. Open a terminal window and give the command gcc -o hello hello.c. This command will translate the C-code to a machine code. The machine code is saved in a named hello.
  4. If you get any error message you have probably done some mistyping. Correct the error and try again.
  5. Now you can run the program just by giving it its name (hello as a command the terminal window. You may have to put a ./ in front of the name depending on how your environment is set up.

    The terminal window should now contain something like this (after the listing of files and the contents of hello.c):

    vranx$ vranx$ ls -l -rwxr-xr-x 1 tom it 7664 Oct 19 13:06 hello* -rw-r--r-- 1 tom it 79 Oct 17 20:44 hello.c vranx$ cat hello.c // A classic starter #include <stdio.h> int main() { printf("Hello world!\n"); return 0; } vranx$ gcc -o hello hello.c vranx$ ./hello Hello world! vranx$

The option "-o hello" on the gcc-command specifies the name of the file containing the executable code. You can choose any name you want. You can actually leave out that option in which case the result will be stored in the file a.out. Try that and run the result!

Each time you make any changes to the program ("the source code") you have save it and recompile before you run it.

Details in the program

Construct Explanation
// A classic starter This line is a comment which does not influence the function at all. A comment starts with double slash and goes to the end of the line.
#include <stdio.h> Lines starting with the #-sign are instructions to a preprocessor.
This particular statement says that a file containing definitions for the standard input/output library should be included.
int main() { This line defines the beginning of a function named main. The function has no parameters (indicated by the empty pair of parentheses ()) and returns a value of integer type.
The particular name main has a special meaning: it defines the starting point for the execution.
printf("Hello world!\n"); This is the first statement that really does something: It calls the function printf which sends the text string "Hello world\n" to the standard output. As seen, strings are enclosed by quotation marks (") but these are not shown in the output.
The printf-function works very similarly to the print-command in Python. The main difference is the syntax.
Statements are ended by semicolons (;).
return 0; Since we declared above that main shall return an integer value we should do that using a return-statement.
} This curly bracket marks the end of main. It matches the forward bracket at the end of the function statement above.
Unlike Python, indentation has no semantic meaning in C - the structure is marked by pairs of curly brackets.
However, indentation is an important way to make the program structure clear for the human eye so use it! All good editors support indentation according to the language in use.

Errors

It is inevitable that we make errors in the programming process. The compiler can discover errors like forgotten semicolons, misspelled names, forgotten declarations etc. The error messages from the compiler are usually (but not always) easy to understand.

Make some changes to the program above like remove a semicolon, remove one of the curly brackets, misspell the printf-function and see what the compiler says. It is important to really read the messages and try to understand what the meaning is!

Unfortunately, the compiler cannot discover all possible errors in a program and, as you will see, it may be much more difficult to find those other errors.

Examples

Here follows a series of annotated programs showing the basic constructs in C. Try them out and make minor modifications!

Example 1: Iteration

Code Explanation
/* squares.c This program writes a table over squares of the numbers 1, 2, ... 10 */ This is a way of writing comments that stretches over several lines.
It starts with /* and ends with */
#include <stdio.h> int main() {
int i = 1; Declares a variable of integer type and gives it a value.
while (i <= 10) { An iteration construction. Note that the condition has to be enclosed in parentheses!
printf("%d \t %d \n", i, i*i); Sends the value of i and i*i to standard output. The %d says that they are to be handled as integers
i = i + 1; Increases the value of i by 1.
} return 0; }

Link to the source code. Copy it and try it out!

Example 2

This example demonstrates
  1. a program with two functions: main and factorial,
  2. the for-statement which is another iteration statement and
  3. the ++- and ---operators.
Code Explanation
/* factorial.c Program that tabulates the factorial function */ #include <stdio.h>
int factorial(int n) { Starts the definition of a function with one parameter of integer type and a return value also of integer type.
int result = 1; while (n > 0) { result = result*n;
n--; Decreases the value of n with one. A shorthand for n = n - 1.
} return result; } The iteration ends and the computed value is returned.
int main() {
Start of main as before.
for (int i = 0; i<=10; i++) { Will repeat the following block with the values 0, 1, 2 , ... 10 on the variable i.
printf( "%2d %15d \n", i, factorial(i)); The contents of the iteration. Notice the call to the factorial function.
} The end of the repeated block.
return 0; } The end of the main function as before.

Exercises

  1. Copy the program from this link. Compile and run it.
  2. Rewrite the while-statement in the factorial function as a for-statement.
  3. Rewrite the for-statement in main as a while-statement.
  4. What happens if you try to compute factorials up to 50 instead of 10? Explain!
  5. Change the order of the function definitions, i.e. put the main-function before the factorial function. What happens when you compile? What happens when you run the program?

Example 3

This example demonstrates
  1. the if-statement and
  2. a recursive function.
Here follows an alternative recursive definition of the factorial function.
Code Explanation
int factorial(int n) { if (n == 0) { return 1; } else { return n*factorial(n-1); } } A conditional statement. The condition has to be enclosed by parentheses.


Note how the function calls itself with a smaller argument.

Exercises

  1. Exchange the original iterative definition of factorial with this recursive definition. Compile, rerun and check that it works.
  2. Check what happens if you call this factorial with a negative argument!
    Rewrite the code so you get an error message if factorial is called with a negative argument!

Notes on data types

The concept of data types is very important in C as well as in many other compiled language. So far we have only been working with int type which, of course, stands for integer.

Integer types

There are several integer types. The most common are char, short, int and long. The main difference is the amount of storage they occupy. A char usually takes one byte of memory and a long at least 4 bytes.
We will mainly use int for integer values.

The integer arithmetic is exact as long as you stay within the underlying hardwares restrictions.

Floating point types

The floating point can represent decimal numbers. The most common types are float (usually 4 bytes) and double (usually 8 bytes)

Floating point constants are written with a decimal point and/or an exponent.
Examples: 1.0, -0.25, 1.0e3, 1E-10.
They will all be of type double.

If you want to specify a constant of type float you have to append the letter f.
Examples: 0.1f, 1e-10f.

Floating point computations may introduce rounding errors.

Mixed mode arithmetic

If both the operands in an arithmetic operation are of integer type, the result will be of integer type. If at least one of the operands is of floating point type, the result will be of floating point type.
Example: 7/2 will be 3 while 7.0/2 will be 3.5.
(Note that the "slash" (/) is used for both integer and floating point division unlike some other languages.)

You can explicitly enforce conversion between types using a type cast operator. They are written as type name enclosed by parentheses.

Some examples:

int m = 3; int n = 2; double x = m/n; // x will become 1.0 double y = (double)(m/n); // y will become 1.0 double z = (double)m/n; // z will become 1.5

The char data type

As mentioned above a char is an integer. Character constants are enclosed by apostrophes.
Examples: 'a', '.', '1', '+'.

Some special character constants have to be preceded by a \ called the escape character.
Examples: '\'' for apostrophe and '\n' for line break.

Since the char is an integer type it is possible to use them in arithmetic.
Examples:

char c = 'a'; printf("c as a character: %c\n", c); printf("c as an integer : %d\n", c); int i = c + 1; printf("i as a character: %c\n", i); printf("i as an integer : %d\n", i); int v = 'x' +'A' - 'a'; printf("v as a character: %c\n", v); printf("v as an integer : %d\n", v);

Copy this program, compile, run and check the printouts!

The library ctype contains functions for character handling. The unix command man ctype will list them.
Use #include <ctype.h> to use them!

Example 4

This example demonstrates reading and writing of characters.
Code Explanation
/* cat.c Copy standard input to standard output. */ #include <stdio.h> int main() {
int c; c = getchar(); Declares a variable and reads one character from standard input. Note that we are using the type int for storing the result from getchar.
while (c != EOF) { EOF is a predefined integer constant which can be retuned by getchar. It indicates that no more characters are available.
putchar(c); c = getchar(); Sends the read character to standard output and
reads the next.
} return 0; }

Exercises

  1. Copy the program and save it under the name cat.c. Compile it and give executable code the name cat. (It is actually a simple variant of the unix-command cat.)
  2. Check that it works using the command ./cat < cat.c. It should produce a listing of its own source code. (If you remove the ./ part you should get the same result produced by the unix command.)
  3. Modify the program so it counts number of copied characters and the number of lines and prints these values at the end. Hint: The getchar function returns the '\n' at the end of a line i.e. if (c == '\n') ... can be used to handle end of lines.

Example 5

In a previous example we demonstrated how single characters could be read using the function getchar. This example demonstrates how numbers can be read.
Code Explanation
/* sum.c Reads and sums positive numbers. Ends when a non positive number is read. */ #include <stdio.h> int main() { double sum = 0; int n = 0; float x;
scanf("%f", &x); The function scanf is used to read values from standard input. The string given as the first parameter contains information about what type of values that should be read. The %f indicates a float value. The second parameter (&x) is the address to the variable x and thus telling C where to store the read value.
while (x > 0) { n++; sum += x; scanf("%f", &x); } Count, sum and read again.
printf("Numbers read : %3d\n", n); printf("Sum of numbers: %5.2f\n", sum); return 0; } Print the answers and leave.

Exercises

  1. Copy the code and run the program and find out what you can have between the numbers (one or more blanks, line breaks, commas, ...?)
  2. Rewrite the program so it sums integers instead of floats. What happens if you enter a decimal number instead of an integer? What happens if you keep %f in scanf instead of changing it to %d for reading integers? Ignore the compiler warning and run the program!

Logical values

The original C did not include a boolean (logical) data type. Any scalar data type (integer, floating point, pointer) can be used. The value 0 is considered as false while all other values are regarded as true.

The standard inclusion file stdbool.h defines the bool as a type and the constants true and false.

In the C99-standard the somewhat strange datatype _Bool was introduced.

A lot of C programmers continue to use the traditional way regarding 0 (or NULL) as false and all other values as true.
For example, an infinite loop can be written:

while (1) { ... }

Example 6

This example demonstrates some new operators and the use of bool type.
Code Explanation
#include <stdio.h> #include <math.h> #include <stdbool.h> We include math.h because we want to use the mathematical function sqrt and stdbool.h because we want to use bool, true and false.
bool isPrime(int n) { for (int i=2; i<=sqrt(n); i++) { if (n%i == 0) { return false; } } return true; } It is enough to check the divisibility up to the square root of n.
The %-sign is the remainder (modulus) operator.



Note that the function could just as well be written without the bool-constructs:

int isPrime(int n) { for (int i=2; i<=sqrt(n); i++) { if (n%i == 0) { return 0; } } return 1; }

Exercises

  1. Copy the code and write a main function that checks if it works.
  2. Write and test a function isTwinPrime(int n) that checks if both n and n+2 are primes.

Go to next lesson.

Valid CSS!