CS253: Software Development with C++

Spring 2021

Pointers

Show Lecture.Pointers as a slide show.

CS253 Pointers

Philosophy

Pointers

An example

int a[] = {11, 22, 33, 44, 55};
int *p = &a[2];
cout << *p << '\n';
p += 2;
cout << *p << '\n';
33
55

Bad examples

int a[] = {11, 22, 33, 44, 55};
int *p = &a[2], n;
n = p;
c.cc:3: error: invalid conversion from 'int*' to 'int'
int a[] = {11, 22, 33, 44, 55};
int *p = &a[2], n;
p = n;
c.cc:3: error: invalid conversion from 'int' to 'int*'

Declaration style

These are all equivalent, since spaces matter little:

int *a;
int* b;
int*c;
int   *   d;
int
*
e;
What types are g and h?

g is an int *, but h is simply an int.

int* g, h;

That’s why I do this:

int *i, j;

Another example

int a[] = {11, 22, 33, 44, 55};
int *p = a;
cout << *p << '\n';
*p += 8;
cout << *p << '\n';
p += 2;
cout << *p << '\n';
11
19
33
int a[5] = {11, 22, 33, 44, 55};
cout << a     << '\n'
     << &a[0] << '\n';
0x7fff7b0cf4d0
0x7fff7b0cf4d0

Null pointers

int xyz, *p = &xyz;
if (p)
    cout << "Hello\n";
Hello

References

A reference is like a pointer, with auto-indirection.

int a[] = {11, 22, 33, 44, 55};
int &r = a[2];
cout << r << '\n';
r += 2;
cout << r << '\n';
33
35

A common use

void f1(string s) {        // call by value
    cout << s << '\n';
}

void f2(const string &s) { // call by const reference
    cout << s << '\n';
}

int main() {
    string taunt = "Your mother is a hamster.";
    f1(taunt);
    f2(taunt);
    return 0;
}
Your mother is a hamster.
Your mother is a hamster.

Use of const

DeclarationExplanation
int *anon-const pointer to non-const ints
const int *bnon-const pointer to const ints
int *const cconst pointer to non-const ints
const int *const dconst pointer to const ints
int &e = …reference a non-const int
const int &f = …reference to a const int

Examples

Declare a pointer to constant integers. We can change the pointer, but not the integers.

int alpha[] = {11,22,33,44,55};
const int *p = alpha;
p += 2;
cout << *p;
33
int beta[] = {11,22,33,44,55};
const int *p = beta;
*p = 42;
c.cc:3: error: assignment of read-only location '* p'

Examples

Declare a constant pointer to integers. We can change the the integers, but not the pointer.

int gamma[] = {11,22,33,44,55};
int *const p = gamma;
*p = 42;
cout << *p;
42
int delta[] = {11,22,33,44,55};
int *const p = delta;
p++;
c.cc:3: error: increment of read-only variable 'p'

Dot or pointer?

Examples

vector<bool> v(42, true);   // v is a vector of bool

cout << v.size() << '\n';
42

Here, we use a dot, because v is an object, not a pointer.

Examples

vector<bool> v(42, true);   // v is a vector of bool
vector<bool> *p = &v;       // p is a pointer to vector of bool

cout << (*p).size() << '\n'
     << p->size()   << '\n';
42
42

Two ways (one ugly, one not) of doing the same thing.

Examples

vector<bool> v(42, true);   // v is a vector of bool
vector<bool> &r = v;        // r is a reference to a vector of bool

cout << r.size() << '\n';
42

Array Name is a Pointer

The name of an array is equivalent to a pointer to its first element.

Write the data via the first pointer, and read it from the second pointer.

double alpha[20];
double *a = alpha;
double *b = &alpha[0];
*a = 123.456;
cout << *b << '\n';
if (a == b)
    cout << "Pointers are equal.\n";
123.456
Pointers are equal.

Arrays & Pointers

You can think of there being two sorts of arrays.

Stack-Based Array Example

The array alpha is on the stack.

int alpha[10];
for (int i=0; i<10; i++)
    alpha[i] = i*i;
for (int i=0; i<10; i++)
    cout << alpha[i] << ' ';
cout << '\n';
cout << "size of alpha: " << sizeof(alpha) << '\n';
0 1 4 9 16 25 36 49 64 81 
size of alpha: 40

Array Example

The pointer beta is on the stack, pointing to ten ints of dynamic memory.

int *beta = new int[10];
for (int i=0; i<10; i++)
    beta[i] = i*i;
for (int i=0; i<10; i++)
    cout << beta[i] << ' ';
cout << '\n';
cout << "size of beta: " << sizeof(beta) << '\n';
delete[] beta;
0 1 4 9 16 25 36 49 64 81 
size of beta: 8

Character-Based Example

const char a[] = "abcdefghijklm";
const char *b  = "nopqrstuvwxyz";
cout << a << ' ' << b << '\n'
     << sizeof(a) << ' ' << sizeof(b) << '\n';
abcdefghijklm nopqrstuvwxyz
14 8

Pointer Arithmetic

Pointer Addition

int data[] = {11,22,33,44,55,66,77,88,99};
int *p = data;      // p points to 11
p += 3;             // p now points to 44
cout << *p << '\n';
44

Let’s look at the pointers:

int data[] = {11,22,33,44,55,66,77,88,99};
int *p = data;
cout << p << '\n';
p += 3;
cout << p << '\n';
0x7fffbcedfbd0
0x7fffbcedfbdc

Pointer Subtraction

Similarly, subtracting pointers yields the number of items, not the number of bytes.

int data[] = {11,22,33,44,55,66,77,88,99};
int *p = data+7;    // p points to 88
cout << *p << '\n';
p--;                // p now points to 77
cout << *p << '\n';
88
77

Pointer Subtraction

No, the other kind of pointer subtraction:

int data[20];
int *a = &data[2], *b = &data[9];
cout << b-a << '\n';    // b is 7 past a
7

More Complicated

Of course, you can have a pointer to any type.

    // pointer to pointer to int:
    int **p;

    // pointer to pointer to pointer to pointer to pointer to int
    int *****q;

    // one hundred pointers to ints:
    int *a[100];

    // pointer to a function that takes a float & a bool and returns an int
    int (*fn)(float, bool);