Computer Systems Org I - Prof. Grishman

Lecture 18 - Nov. 3, 2005

Pointers and address arithmetic

In writing machine language code to access array elements, we saw how this involved address arithmetic: 
the address of a[i] = the address of a[0] + i
In C,  if 'a' is an array, then 'a' used alone (without a subscript) represents the address of a[0].  So we can do address (pointer) arithmetic explicitly in C, and write, instead of a[i], *(a+i).  This means 'add i to the address of array a, and then get the contents of the word at that address'.

In the programs below, we use a pointer into a character array (char *).  It starts by pointing to the first element of the array (first character of the string) and then is incremented to point to successive elements of the string.

#include <stdio.h>

int ourstrlen (char[]);

main () {
        int len;
        char stg[10];
        printf ("Enter a string>");
        scanf ("%s", &stg);
        len = ourstrlen (stg);
        printf ("Length of %s = %d", stg, len);
}

int ourstrlen (char* s) {
        int counter = 0;
        while (*s++) counter++;
        return counter;
}

A slightly faster version uses two pointers:  s continues to point to the beginning of the string, while p advances through the string.  At the end we compute the difference between the two addresses:

#include <stdio.h>

int ourstrlen (char[]);

main () {
        int len;
        char stg[10];
        printf ("Enter a string>");
        scanf ("%s", &stg);
        len = ourstrlen (stg);
        printf ("Length of %s = %d", stg, len);
}

int ourstrlen (char* s) {
        char* p = s;
        while (*p++) ;
        return p-s-1;
}

A function for copying a string, using arrays:

#include <stdio.h>

void ourstrcpy (char[], char[]);

main () {
        char first[10];
        char second[10] = "xxxxxxxxx";
        printf ("Enter a string>");
        scanf ("%s", &first);
        ourstrcpy (first, second);
        printf ("Second = %s", second);
}

void ourstrcpy (char a[], char b[]) {
        int i = 0;
        while (a[i] != 0)
        {
                b[i] = a[i];
                i++;
        }
        b[i] = 0;
}

An equivalent string-copying function, using pointers, and trying very hard to make it as short as possible:

#include <stdio.h>

void ourstrcpy (char[], char[]);

main () {
        char first[10];
        char second[5] = "xxxx";
        printf ("Enter a string>");
        scanf ("%s", &first);
        ourstrcpy (first, second);
        printf ("Second = %s", second);
}

void ourstrcpy (char* a, char* b) {
        while (*b++ = *a++);
}

Returning a string from a C function

Suppose we wanted to write a function getline which returns as its value the next line of input.  We first wrote

#include <stdio.h>

char* getline();

main () {
        char* p;
        p = getline();
        printf ("Line is %s", p);
}

char* getline () {
        char line[20];
        char c;
        int i = 0;
        while (i<20 && (c = getchar()) != '\n')
                line[i++] = c;
        return line;
}

but this version is problematic because the array 'line' is allocated on the stack and may be overwritten by the next function call after getline.
We can remedy this by using a global, statically allocated line variable (we did not present this version in class):

#include <stdio.h>

char* getline();

char line[20];

main () {
        char* p;
        p = getline();
        printf ("Line is %s", p);
}

char* getline () {
        char c;
        int i = 0;
        while (i<19 && (c = getchar()) != '\n')
                line[i++] = c;
        line[i] = 0;
        return line;
}

We also were careful this time to add a zero character to the end of the string.  This works fine, so we were more ambitious and tried to read and write two lines with the following main program ...

main () {
        char* p;
        char* q;
        p = getline();
        q = getline();
        printf ("First line is %s\n", p);
        printf ("Second line is %s\n", q);
}

However, when we typed in 'moo' followed by 'quack' it responded with two 'quack's.  We just had a single array 'line' which was being used for both lines.   How to solve this problem ... tune in next class.