Pulsars and neutron stars/Introduction to C for pulsar astronomers

Introduction
Many of the pulsar-based software packages are written in C (such as tempo2 and sigproc).

C programs are first written as a text file (or set of text files) using a text editor (there are specific editors for writing programs, but it is also possible to use emacs or vi). The programs then need to be compiled before they can be run. Any changes to the programs require re-compiling.

You can check that you have gcc installed, and the version number using

 $ gcc -v

A basic program
Save the code as test.c. Compile using  $ gcc test.c This produces an output file called "a.out". To run  $ ./a.out You can also use:  $ gcc -o test test.c and that makes the output file called "test" which can be run using  $ ./test

Functions
The programmer can create their own functions. These may be functions that will only be used in the particular program currently being written or may be used more often in lots of different programs.

A function can simply package up a bit of code that may be run multiple times.

Note that functions cannot access data from outside the function (unless you use global variables - don't). So, if you define a value in one function, it cannot be directly used in another function.

In the above example, x = 5 in the main function and 10 in the new function.

It is possible to make a function return a value. Note that C functions can only (easily) return a single value.

This should display that x is 5, then 10 and then 10 again.

It is also useful to pass values to a function:

Loops
Programs in C basically start at the top and then go to the bottom of each function. There are a few ways to repeat parts of the function. We can use "for", "while" or "do" loops as follows.

This should print out x = 10, x = 11 ... x = 19 on the screen. First x is set (x=10). It then checks whether x < 20, it is! Then it carries out all the statements between the curly-brackets. At the end bracket it adds one to x (x = x + 1) and then re-does the check to see if x < 20.

There are a few simplifications. Instead of writing x = x + 1; you can write

For x = x + 2, you can write:

Another simplification is that curly-brackets are not needed in loops if the loop only has one command:

It is also possible to use a while loop:

Note that a while loop will do the check (x < 20) before carrying out any of the commands inside the loop. In contrast a "do" loop does the check at the end:

Conditional statements
Often some commands should only be run in some cases. For instance:

Again, this can be simplified to:

Note:
 * < less than
 * <= less than or equal to
 * > greater than
 * >= greater than or equal to
 * == equals
 * != does not equal

Arrays
Instead of creating a variable that contains a single number, it is possible to create an array of values (or characters). Let's allocate 5 numbers:

We can set the values in a loop:

Note that the compiler will not check whether you are actually using the allocated memory. In the above example you allocated an array of size 5, but you can actually write y[100] = 10. This will probably cause a segmentation fault when you run the code, but may also crash the computer!

Strings
Strings are words or phrases. In C they are actually arrays of characters. Characters are stored as "char":

The integer value for each character can be found in tables of ASCII characters. A capital "A" is 65, "B" = 66, etc.

To make a string we need an array of characters

Notice that C doesn't know where the end of the string actually is and it may be producing junk on your screen. You can use the end of string character "\0" to fix this:

Now the string should stop at the correct position. Creating strings this way is clearly not very practical. Instead you can use a "C" library that provides functions for processing strings.

also take a look at strcasecmp, strlen and strstr. Note that in C you cannot write:

instead you have to use strcpy.

Getting information into the program
Currently you can input data directly in the program:

However, often the user wishes to input values or the information should be obtained from the command-line or from a file.

Getting input from the keyboard
For a string, use:

Note that there is a danger in using scanf. It doesn't check to make sure that you actually are typing in e.g., an integer. You could ask "what is you name?" and the user types "hello" or "-3.23" or anything else. This may cause the program to crash or give incorrect results. When reading a string, you need to define the maximum number of characters (256 in the above example). C doesn't check to make sure that the user does actually write fewer than this many characters. If more, then the program may crash. There are other routines (e.g., "gets", "fgets" etc. that can help with this).

Command line arguments
When you run your program from the command line you normally type something like

You can also pass command line arguments such as:

To read these into the code, use the following

Often we need to read an argument in a variable. For instance, let's run

To determine k, n and title we need something like the following:

Reading and writing files
Let's assume that we have a file that contains two rows of numbers. We wish to read in those numbers, add them together and produce a new file containing the sum. Let the input file be called in.dat and have the following content:

We can read it in and print it to the screen as

Now let's write the addition out to a new file

Pointers
Pointers can be very confusing. Writing:

allocates part of memory, labels it as "x" and stores the number 5. This can be accessed or modified using the label, e.g.,

You can also determine the actual memory location using the ampersand (&) operator:

Passing the memory location allows you to modify a bit of memory in another function

In summary, a pointer is a variable (e.g., it must be declared and it has a label etc.) whose value is the memory address of another variable. To declare a pointer use the * symbol. To obtain the address of a normal variable use the & symbol.

Pointers can be very powerful and can make your code very fast. Here is the use of a pointer to print out the elements of an array:

Structures
Structures provide the means to move away from the simple variable types (int, float, double) defined by C. For instance, a pulsar observation may have an observation time, a frequency, a pre-fit residual, a post-fit residual, etc. etc.  This can be set up using a structure as follows:

If a pointer is being used then the -> symbol is used instead of the "." symbol: