7  Pointers

7.1 Introduction to Pointers

Objects, Sizes, and Addresses

Each variable (object) has an address and a size. The address is where it sits and the size is how many memory locations it takes up.

address 100 101 102 103 104 105
memory

Size Operator

  • The size can be retrieved using the size operator sizeof
#include <iostream>
using namespace std;
int main() {
    char c;
    cout << sizeof(char) << " " << sizeof(c) << endl;
    int i;
    cout << sizeof(int) << " " << sizeof(i) << endl;
    double d;
    cout << sizeof(double) << " " << sizeof(d) << endl;
    return 0;
}

Address Operator

  • The address can be retrieved using the address operator &
#include <iostream>
using namespace std;
int main() {
    char c = 1;
    cout << int(c) << " " << &c << endl;
    int i = 2;
    cout << i << " " << &i << endl;
    double d = 3.0;
    cout << d << " " << &d << endl;
    return 0;
}

What is Pointer

A pointer is a variable that stores addresses of memory locations (addresses of other objects).

  • The null pointer does not point to anything

Pointer’s Usage

Pointers have several uses, including:

  • Creating fast and efficient code
  • Providing a convenient means for addressing many types of problems
  • Supporting dynamic memory allocation
  • Making expressions compact and succinct

Declaring Pointers

  • A pointer being a variable needs to be declared like all variables do
⟨Pointed Type⟩ * ⟨Pointer Variable Name⟩;
  • A pointer to void is a general-purpose pointer used to hold references to any data type.
void *pv;
  • Declare pointer type
typedef ⟨Pointed Type⟩ * ⟨Pointer Type Name⟩;
  • Example
typedef int * IntPointer;
int *p1;          // pointer to an integer
IntPointer p2;    // pointer to an integer

Pointer Operators

Operator Name Meaning
* Dereference Used to dereference a pointer
-> Point-to Used to access fields of a structure referenced by a pointer
+, +=, ++ Addition, increment Used to increment a pointer
-, -=, -- Subtraction, decrement Used to decrement a pointer
== != Equality, inequality Compares two pointers
> >= < <= Greater than, greater than or equal, less than, less than or equal Compares two pointers
⟨data type⟩ Cast To change the type of pointer

Dereferencing a Pointer

int num = 5;
int *pi = &num;
*pi = *pi + 2;
printf("%d\n",*pi);

Adding an integer to a pointer

int vector[] = {28, 41, 7};
int *pi = vector;      // pi: 100

printf("%d\n",*pi);    // Displays 28
pi += 1;               // pi: 104
printf("%d\n",*pi);    // Displays 41
pi += 1;               // pi: 108
printf("%d\n",*pi);    // Displays 7

Subtracting an integer from a pointer

int vector[] = {28, 41, 7};
int *pi = vector + 2;  // pi: 108

printf("%d\n",*pi);    // Displays 7
pi--;                  // pi: 104
printf("%d\n",*pi);    // Displays 41
pi--;                  // pi: 100
printf("%d\n",*pi);    // Displays 28

Subtracting two pointers

int vector[] = {28, 41, 7};
int *p0 = vector;
int *p1 = vector+1;
int *p2 = vector+2;

printf("p2-p0:  %d\n",p2-p0);    // p2-p0:  2
printf("p2-p1:  %d\n",p2-p1);    // p2-p1:  1
printf("p0-p1:  %d\n",p0-p1);    // p0-p1:  -1

Comparing Pointers

int vector[] = {28, 41, 7};
int *p0 = vector;
int *p1 = vector+1;
int *p2 = vector+2;

printf("p2>p0:  %d\n",p2>p0);    // p2>p0:  1
printf("p2<p0:  %d\n",p2<p0);    // p2<p0:  0
printf("p0>p1:  %d\n",p0>p1);    // p0>p1:  0

Multilevel Pointer

A pointer can store the address of another pointer variable.

int num = 100;
int *p1;
int **p2;
int ***p3;
p1 = &num;
p2 = &p1;
p3 = &p2;

7.2 Constants and Pointers

Const

Using the const keyword to protect variables from changing

Pointer Type Pointer Modifiable Data Pointed to Modifiable
Pointer to a nonconstant \checkmark \checkmark
Pointer to a constant \checkmark X
Constant pointer to a nonconstant X \checkmark
Constant pointer to a constant X X

Pointer to a constant

int num = 5;
const int limit = 500;
int *pi;                // Pointer to an integer
const int *pci;         // Pointer to a constant integer

pi = &num;
pci = &limit;

Constant pointer to a nonconstant

int num = 5;
int *const cpi = &num;

Constant pointer to a constant

const int limit = 500;
const int * const cpci = &limit;

7.3 Pointers and Arrays

One-Dimensional Arrays

  • Example
int array[5];
int *p = array + 2;

  • Technique
T * range_begin = array;
T * range_end = array + n; // n is the length of the array
for (T *p = range_begin; p < range_end; p++) {
  // do something
}

Pointer to Arrays

  • Syntax
⟨Data Type⟩ (* ⟨Pointer Variable Name⟩)[⟨Size of Array⟩];
  • Example
int (*p1)[10];
double (*p2)[50];

Two-Dimensional Arrays

  • Row major
  • Column major

2D row major

\begin{align*} offset & \longleftrightarrow(row,column)\\ offset & =row\times N_{column}+column \end{align*}

2D column major

\begin{align*} offset & \longleftrightarrow(row,column)\\ offset & =column\times N_{row}+row \end{align*}

Multidimensional Arrays

int A[2][3] = {
  { 1, 2, 3 },
  { 4, 5, 6 }
};

int B[2][2][3] = {
  { { 1, 2, 3 }, {  4,  5,  6 } },
  { { 7, 8, 9 }, { 10, 11, 12 } }
};

7.4 Pointers and Functions

Passing Data by Value

void swap(int num1, int num2) {
    int tmp;
    tmp = num1;
    num1 = num2;
    num2 = tmp;
}
int main() {
    int n1 = 5;
    int n2 = 10;
    swap(n1, n2);
    return 0;
}

Passing Data Using a Pointer

void swapWithPointers(int* pnum1, int* pnum2) {
    int tmp;
    tmp = *pnum1;
    *pnum1 = *pnum2;
    *pnum2 = tmp;
}
int main() {
    int n1 = 5;
    int n2 = 10;
    swapWithPointers(&n1, &n2);
    return 0;
}

Passing a Pointer to a Constant

void passingAddressOfConstants(const int* num1, int* num2) {
    *num2 = *num1;
}
int main() {
    const int limit = 100;
    int result = 5;
    passingAddressOfConstants(&limit, &result);
    return 0;
}

Returning a Pointer

int* allocateArray(int size, int value) {
    int* arr = new int[size];
    for(int i=0; i<size; i++) {
        arr[i] = value;
    }
    return arr; 
}

several potential problems can occur when returning a pointer from a function, including:

  • Returning an uninitialized pointer
  • Returning a pointer to an invalid address
  • Returning a pointer to a local variable
  • Returning a pointer but failing to free it

Function Pointers

A function pointer is a pointer that holds the address of a function.

⟨Return Type⟩ (* ⟨Pointer Variable Name⟩)(⟨...⟩);
int (*f1)(double);       // Passed a double and 
                         //    returns an int
void (*f2)(char*);       // Passed a pointer to char and 
                         //    returns void
double* (*f3)(int, int); // Passed two integers and 
                         //    returns a pointer to a double
  • Declare function pointer type
typedef ⟨Return Type⟩ * ⟨Pointer Type Name⟩(⟨...⟩);

Using a Function Pointer

int (*fptr1)(int);
int square(int num) {
    return num*num;
}
int main() {
    int n = 5;
    fptr1 = square;
    printf("%d squared is %d\n",n, fptr1(n));
}

7.5 Pointers and Structures

Pointers and Structures

  • Declare a structure
struct Person {
    char firstName[100];
    char lastName[100];
    char title[10];
    unsigned int age;
};
  • Declare a pointer
Person *p;

Point-to Operator

  • Access the fields of a structure variable
cout << p->title;
cout << (*p).age;
  • The awkwardness of this expression (*p).age shows the necessity of the -> operator.
  • Remember that the operators -> and . for selecting members of structures have higher precedence than the dereferencing operator *.
Expression Meaning
s->m
*a.p
(*s).m
*s->p
*(*s).p

7.6 Workshop

Quiz

  1. What is a pointer?

Exercises

7.7 References