Lecture 15 More Pointers

Joseph Haugh

University of New Mexico

Review Quiz

What is the output of the following pieces of code?

Review Quiz

void foo(int arr[], int n) {
    int i, k, j;
    for (i = 1; i < n; i++) {
        k = arr[i];
        j = i - 1;
        while (j >= 0 && arr[j] > k) {
            arr[j + 1] = arr[j];
            j = j - 1;
        }
        printf("arr[%d+1]=%d\n", j, k);
        arr[j + 1] = k;
    }
}
void main(void) {
    int arr[] = {5, 2, 4, 6, 1, 3};
    int n = 6;
    foo(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

Review Quiz

arr[-1+1]=2
arr[0+1]=4
arr[2+1]=6
arr[-1+1]=1
arr[1+1]=3
1 2 3 4 5 6

Review Quiz

void shaker(int arr[], int n) {
    int swp = 1;
    while (swp) {
        swp = 0;
        for (int i = 0; i < n - 1; i++) {
            if (arr[i] > arr[i+1]) {
                sw(arr, i, i+1);
                swp = 1;
            }}
        if (!swp) break;
        n--;
        for (int i = n - 1; i > 0; i--) {
            if (arr[i] > arr[i+1]) {
                sw(arr, i, i+1);
                swp = 1;
            }}
    }}
void sw(int arr[], int x, int y) {
    printf("swing: x=%d, y=%d\n", 
           x, y);
    int t = arr[x];
    arr[x] = arr[y];
    arr[y] = t;
}

void main(void) {
    int arr[] = {5, 2, 4, 6, 1, 3};
    int n = 6;
    shaker(arr, n);
    for (int i = 0; i < n; i++) {
        printf("%d", arr[i]);
    }
    printf("\n");
}

Review Quiz

swing: x=0, y=1
swing: x=1, y=2
swing: x=3, y=4
swing: x=4, y=5
swing: x=2, y=3
swing: x=1, y=2
swing: x=0, y=1
swing: x=3, y=4
swing: x=2, y=3
123456

Review Quiz

void main(void) {
    int x = 5;
    int *y = &x;
    *y + 3;
    printf("x=%d\n", x);
}

Review Quiz

void main(void) {
    int x = 5;
    int *y = &x;
    *y + 3;
    printf("x=%d\n", x);
}
x = 5

Review Quiz

void main(void) {
    int x = 5;
    int y = *(&x) + 3;
    printf("x=%d, y=%d\n", x, y);
}

Review Quiz

void main(void) {
    int x = 5;
    int y = *(&x) + 3;
    printf("x=%d, y=%d\n", x, y);
}
x = 5, y = 8

Review Quiz

void main(void) {
    /* Assume sizeof(int) = 4 */
    int x = 5; /* addr = 0x40 */
    int *y = &x + x;
    printf("&x=%p, y=%p\n", &x, y);
}

Review Quiz

void main(void) {
    /* Assume sizeof(int) = 4 */
    int x = 5; /* addr = 0x40 */
    int *y = &x + x;
    printf("&x=%p, y=%p\n", &x, y);
}
&x=0x40, y=0x54

Pointer Arithmetic

Recall that the following code:

int x = 5;
int *ptr = &x;
ptr = ptr + 3;

Really means this:

int x = 5;
int *ptr = &x;
ptr = ptr + 3 * sizeof(int);

Pointer Arithmetic

Pointer arithmetic depends on the type of the pointer.

For example given this code:

ptr = 100;
ptr = ptr + 3;
Type Size Result
char * 1 103
short * 2 106
int * 4 112
int ** 4 112
struct foo * sizeof(struct foo) 100 + 3 * sizeof(struct foo)

Pointer Arithmetic

Have you ever considered how arrays are implemented?

You have probably heard arrays described as a contiguous block of memory.

What does contiguous mean in this context?

There are no gaps in the memory.

With this in mind can you see how we could implement arrays using pointers?

Pointers as Arrays

Pointer arithmetic can be used to implement arrays:

int *arr;
arr = malloc(3 * sizeof(int));
*(arr) = 0
*(arr + 1) = 1;
*(arr + 2) = 2;

This fills the first three elements of the array with 0, 1, and 2.

Pointers as Arrays

int *arr;
arr = malloc(3 * sizeof(int));
*(arr) = 0
*(arr + 1) = 1;
*(arr + 2) = 2;
Address Value
0x100
0x104
0x108

Pointers as Arrays

int *arr;
arr = malloc(3 * sizeof(int));
*(arr) = 0
*(arr + 1) = 1;
*(arr + 2) = 2;
Address Value
0x100 0
0x104
0x108

Pointers as Arrays

int *arr;
arr = malloc(3 * sizeof(int));
*(arr) = 0
*(arr + 1) = 1;
*(arr + 2) = 2;
Address Value
0x100 0
0x104 1
0x108

Pointers as Arrays

int *arr;
arr = malloc(3 * sizeof(int));
*(arr) = 0
*(arr + 1) = 1;
*(arr + 2) = 2;
Address Value
0x100 0
0x104 1
0x108 2

Danger Will Robinson!

You have to be careful to allocate enough memory for the array.

If you execute this code:

int *arr;
arr = malloc(3 * sizeof(int));
*(arr + 3) = 3;

You will be writing to memory that you do not own!

The compiler will not catch this error for you!

Square Brackets

What does arr[x] really mean?

arr[x] = *(arr + x)

A Trick

arr[x]
*(arr + x)
*(x + arr)
x[arr]

Try it! It works but shouldn’t be used in practice.

Array Element Addresses

  • You can get the address of individual array elements:
&array[1]     /* address of the second element            */
&array[0]     /* address of the first element             */
array         /* address of the first element             */
int *array[3] /* allocates an array of three int pointers */

Type Sizes

  • Is int the same size as int *?

  • As with most things in C it depends

  • On a 64 bit machine (which most machines are these days) it is not!

  • Try this:

    void main(void) {
        printf("%d\n", sizeof(int));
        printf("%d\n", sizeof(int *));
    }

Arrays as Parameters

  • Arrays can be passed as parameters and are passed by value but the value is the address of the first element

    void foo(int bar[3]) {
    bar[0] = 0;
    bar[1] = 2;
    }
    
    void main(void)  {
    int array[3];
    foo(array);
    }
  • First element is now 0 and second element is 2.

Arrays as Parameters

  • You can also pass arrays of variable size by passing in the length of the array as a separate parameter

    void foo(int bar[], int count) {
    int i;
    for (i = 0; i < count; i++) 
        bar[i] = i;
    }
    
    void main(void) {
    int array[3];
    }

Arrays as Parameters

  • Remember that passing an array is the same as passing a pointer:

    void foo(int *bar, int count)  {
    int i;
    for (i = 0; i < count; i++)
        bar[i] = i;
    }
    
    int main(void) {
        int array[3];
        foo(array, 3);
        return 0;
    }