Pointer (2)

Posted by blueskyson on February 19, 2020

Pointer Arithmetic

In the previous post, we mentioned that an array is actually a pointer. Array pointers support to return a shifted address via + operator and - operator. Now we learn how to shift an address of elements in array in pointer way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include<iostream>
#include<string>
using namespace std;

int main() {
    int a[10], *p, *q;

    for (int i = 0; i < 10; ++i) //init
        a[i] = i * 10;

    p = a;      //assign an address
    q = a + 5;  //assign another address via pointer arithmetic
    cout << "the address stored in p: " << p  << endl;
    cout << "the address stored in q: " << q  << endl;
    cout << "the value of p:          " << *p << endl;
    cout << "the value of q:          " << *q << endl;
    cout << endl;

    cout << "the address in p + 2:    " << p + 2    << endl;
    cout << "the value of *(p + 2):   " << *(p + 2) << endl;
    cout << "the value of   p[2]:     " << p[2]     << endl;
    cout << "the address of q - 4:    " << q - 4    << endl;
    cout << "the value of *(q - 4):   " << *(q - 4) << endl;
    cout << "the value of   q[3]:     " << q[3]     << endl;
    return 0;
}
the address stored in p: 0x6dfebc
the address stored in q: 0x6dfed0
the value of p:          0
the value of q:          50

the address in p + 2:    0x6dfec4
the value of *(p + 2):   20
the value of   p[2]:     20
the address of q - 4:    0x6dfec0
the value of *(q - 4):   10
the value of   q[3]:     80

Besides shift pointer with an integer, we can subtract one pointers from another to get the distance of these two pointers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include<iostream>
#include<string>
using namespace std;

int main() {
    int a[10], *p, *q;

    for (int i = 0; i < 10; ++i) //init
        a[i] = i * 10;

    p = &a[7];  //assign an address
    q = &a[3];  //assign another address via pointer arithmetic
    cout << "the address stored in p: " << p  << endl;
    cout << "the address stored in q: " << q  << endl;
    cout << "the value of p:          " << *p << endl;
    cout << "the value of q:          " << *q << endl;
    cout << endl;

    cout << "the distance from p to q: " << q - p    << endl;
    cout << "the distance from q to p: " << p - q    << endl;
    return 0;
}
the address stored in p: 0x6dfed8
the address stored in q: 0x6dfec8
the value of p:          70
the value of q:          30

the distance from p to q: -4
the distance from q to p: 4

pointer subtraction

Notice that subtracting two pointers pointing to different array will cause undefined behavior.

Combining the * and ++ Operators

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include<iostream>
#include<string>
using namespace std;

int main() {
    int a[10], *p;
    for (int i = 0; i < 10; ++i) //init
        a[i] = i * 10;

    p = &a[7];  //assign an address
    cout << "the address stored in p: " << p  << endl;
    cout << "the value of p:          " << *p << endl;
    cout << endl;

    cout << "cout *p++   : " << *p++   << endl;
    p = &a[7];  //keep p pointing to a[7]
    cout << "cout *(p++) : " << *(p++) << endl;
    p = &a[7];
    cout << "cout (*p)++ : " << (*p)++ << endl;
    a[7] = 70;  //keep a[7] equaling 70
    cout << "cout *++p   : " << *++p   << endl;
    p = &a[7];
    cout << "cout *(++p) : " << *(++p) << endl;
    p = &a[7];
    cout << "cout ++*p   : " << ++*p   << endl;
    a[7] = 70;
    cout << "cout ++(*p) : " << ++(*p) << endl;
    a[7] = 70;

    return 0;
}
the address stored in p: 0x6dfedc
the value of p:          70

cout *p++   : 70
cout *(p++) : 70
cout (*p)++ : 70
cout *++p   : 80
cout *(++p) : 80
cout ++*p   : 71
cout ++(*p) : 71

Using -- operator will demonstrate similar effects.

Pointer and Multidimensional Array

As we have said in Array and String, C++ stores arrays in row-major order. That means a multidimensional array is seen as a sequence of data assembled by many one dimensional arrays.

array-2

Use the features of pointer, we can process arrays easier. Here’s an example of initializing a three dimensional array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int arr[10][10][10];

//non-pointer process
for (int i = 0; i < 10; ++i)
    for (int j = 0; j < 10; ++j)
        for (int k = 0; k < 10; ++k)
            arr[i][j][k] = 0;

//pointer process
int *p = &arr[0][0][0]; //the same as: int *p = arr;
for (; p <= &arr[9][9][9]; ++p)
    *p = 0;

/*
    By the way, Here is a faster initialization method.
    This method can only be used to initialize elements to 0.
    #include<cstring>
    . . .
    int arr[10][10][10]
    memset(arr, '\0', sizeof(arr));
*/  

We can also process single row of a multidimensional array

1
2
3
4
5
int arr[10][10][10];
int *p;
//initialize the 0th row of arr
for(p = arr[0][0]; p < arr[0][0] + 10; p++)
    *p = 0;