Chapter 6 : Pointers

Chapter 6 : Pointers

Contents

6.1. Simple pointers

The (monadic) operator "&" is "address of", while "*" is "object pointed at by". The variable name is "pointer" (no star).

Pointers are typed by the object they point at; you can't assign the address of a long int into a pointer to an int.

Note well

When you declare a pointer, it is not initialised to point at anything, unless you set it. To declare

and to then use

will generate an error. You must first initialise the pointer with

or initialise it in the declaration with

is OK.

Note also ...

The notation for an initialised pointer declaration

is perfectly acceptable with the meaning of

but can be confusing to read. In the abbreviated version, we are declaring "*point" but assigning to "point". Although it is written "*point\ =\ ..." it actually means "point\ =\ ...".

6.1.1. Pointers and arrays

In general "<pointer> plus-or-minus <integer>" gives a pointer; and "<pointer> minus <pointer>" gives an integer.

6.1.2. Pointers for loops

To sum the elements of an initialised array, use a terminating zero.

To count characters in an array of characters terminated by a '.' use:

6.1.3. Priorities

The expression "*p++" is interpreted as "*(p++)", i.e. increment "p", deliver what it previously pointed at.

Whereas "(*p)++" increments whatever "p" points at. Given

then

is equivalent to

but

is equivalent to

Some pointer examples

We will give two simple example programs, each in two forms, firstly using subscripts in the arrays, then using pointers.

To read two arrays of floats, and form their scalar product.

To print the first few lines of a Pascal triangle.

6.1.4. Double pointers (pointers to pointers)

We will assume that we are given an int variable "i" and an array "a" of 9 ints

We then declare an array "pa" of 3 pointers to ints, either as

or exactly equivalent

We then declare a single pointer to pointer to int, either as

or exactly equivalent

Now add two more declarations of general point to int and pointer to pointer to int.

The above data can be represented pictorially as follows.

I have laid them out so that the top row are all "int"s, the next row "pointers to int" or "int *", the bottom row "pointers to pointers to int" or "int **".

We can now get the value of "pa[0]" by either "*ppa" or "*ppi".

Using double pointers, we can refer to "a[0]" as "**ppa" or "**ppi" or "*pa[0]".

If we execute

we get the revised picture

The value of "*ppi" is now "pa[1]", "**ppi" is now "a[3]", and "*pi" is now "a[1]".

Note the importance of order of evaluation in

which is equivalent to

and

which is equivalent to

and

which is equivalent to

Ragged Arrays

Another way of obtaining a structure similar to the above is as follows.

If we execute

A typical for loop might now be:

6.2. Strings

Strings are handled specially in C.

The denotation "eric" (including the quote signs) is valid anywhere (not just in global), and delivers a pointer to a preassigned string of characters

Note the terminating zero. Thus we can have

or

Because of the terminating zero convention we can write

6.2.1. Strings in C

All strings in C are assumed to be character arrays which end with a null, for example in

the variable "name" must be a character pointer, and characters are printed until a null is found.

[What's the difference between "printf(\ name\ )" and "printf(\ "%s",\ name\ )"?]

To copy the string pointed at by "q" into the area pointed at by "p" (they must both be of type "char *"), we use

To compare two strings (until a null is encountered) pointed at by p and q

6.2.2. String libraries

The library functions for strings include

See the on-line manual "man string" for further details.

6.2.3. The "system" routine (Unix only)

The call

causes the program to be suspended while the command "who" is executed (with its standard input and output connected to the terminal), after which program execution continues. The "system" call actually calls a shell to interpret the string.

6.2.4. Arrays of strings

Arrays of strings (of assorted lengths) are often necessary, in looking up command names, people's names, names of months, ... They are declared as

This sets up an array of pointers to characters, with a null pointer at the end of each string and at the end of the array of pointers. Now add

Boxes at right are "char".
Boxes in middle are "pointer to char" or "char *".
Box at left are "pointer to pointer to char" or "char **".

6.2.5. Using the "char *[]"

We can do the following:

6.2.6. sprintf and sscanf

The same as printf and scanf, but an extra first parameter, a "char *", used instead of actual i/o.

6.3. Parameters to the program.

When a command (calling a program) is issued with parameters, as in

the system generates an integer argc counting the arguments (four in this case) and an object argv set up to represent the command line, as in

("argc" means argument count, "argv" means argument values.) Both of these data items can be picked up from the main program.

6.3.1. Accessing the parameters

Use

The parameter "argv" is the assembled array of strings (including the command name, "a.out" in this case), while "argc" is the number of (non-null) entries. ("argc" is not essential, since its value could be found by scanning through "argv"; it is just convenient; you must include it.) The data in the variables is set up by the system.

6.3.2. The echo command

To print out the arguments (which is what the "echo" command does), the program would be

or, with a more pointer-oriented method,

6.3.3. Unix-type flags

To work out the code to pick up the flags in "cc -s -O prog.c", we first look at the "argv" data as set up by the system.

The code to look for flags would be:

You could, of course, do all this with pointers instead of subscripts.

After a single "argc--; argv++;" the picture becomes

After the loop is finished we have the picture

6.3.4. Other flags

The above code handles separate flags such as "cc\ -s\ -c\ prog". If the flags occur several together, as in "ls\ -lrt" use

6.3.5. Values from arguments

To read numeric values from arguments, use the "atoi" (ASCII to integer) function as follows.

or

6.3.6. The environment

A third parameter of the same type as "argv" can be used to pick up your UNIX environment ...

where "envp" contains pointers to strings such as "USER=ef", "TERM=vt100", and so on, and is null terminated. The library function "getenv(\ "USER"\ )" then delivers a pointer to the string following "USER=" if it can find one starting "USER=".

6.4. Pointers and structures

6.4.1. Basics

Pointers can be used with structures, using all the techniques explained above. There is one significant extension relating to the operator "->".

What is meant to look like an arrow is formed of a '-' and a '>'. It is preceded by a pointer to a structure, and followed by a fieldname.

6.4.2. Structures for lists

6.4.3. Planting Structures

Copyright Eric Foxley 1996


Notes converted from troff to HTML by an Eric Foxley shell script, email errors to me!