Chapter 4 Pointers
Chapter 4 Pointers
R
1 Introduction
Pointer
LU
A pointer is a variable that stores memory address of another variable.
Normally, a variable directly contains a specific value. A pointer contains the memory address of a variable
that, in turn, contains a specific value. In this sense, a variable name directly references a value, and a
pointer indirectly references a value. Referencing a value through a pointer is called indirection.
U
Figure 1 typically represent a pointer as an arrow from the variable that contains an address to the variable
located at that address in memory.
G
N
.A
Just like other variables in C, pointers must be declared before being used. The general syntax for pointer
R
declaration is
1 data type ∗variable name;
D
declares a pointer named ptr which will store a reference to a memory location that can store a double.
Each variable being declared as a pointer must be preceded by an asterisk (*). For example, the declaration
1 float ∗ptr1, ∗ptr2, ∗ptr3
Pointers should be initialized to 0, NULL or an address of the corresponding type either when theyre de-
clared or in an assignment. A pointer with the value 0 or NULL points to nothing and is known as a null
pointer. Symbolic constant NULL is defined in several standard library headers to represent the value 0.
Initializing a pointer to NULL is equivalent to initializing a pointer to 0, but in C, 0 is used by convention.
Dr. Raphael Angulu, BCS 111 SCI, MMUST, 2020: Pointers Notes 1
When 0 is assigned, its converted to a pointer of the appropriate type. The value 0 is the only integer value
that can be assigned directly to a pointer variable without first casting the integer to a pointer type. [Note:
In the new standard, you should use the constant nullptr to initialize a pointer instead of 0 or NULL. Several
C compilers already implement this constant.]
Memory addresses are represented in hexadecimal number. To display a hexadecimal number, we use %x
or %X for formatting. If you use capital X, the hexadecimal alphabets (A-F) are displayed in capital, and
vice-versa. For instance, the code below
1 #include<stdio.h>
2 int main()
3 {
R
4 int count = 7;
5 int ∗countPtr = &count;
6 printf (”count = %d\n”, count);
7 printf (”Address of count = %X\n”, &count);
8 printf (”Value stored in countPtr = %X\n”, countPtr);
LU
9
10 return 0;
11 }
displays U
G
Figure 2: Output of the code above
N
You can see in output in Figure 2 that countPtr actually stores the address of variable count.
The address operator (&) is a unary operator that obtains the memory address of its operand. For example,
1 float a = 10;
2 float ∗aPtr;
3 aPtr = &a;
R
Line 1 declares a variable of type float and assign it a value, line 2 declares a pointer that can store an
address of memory location holding a float and line 3 takes the memory address (reference) of the variable
declared in line 1 and assign it to a pointer declared in line 2.
D
The * operator, commonly referred to as the indirection operator or dereferencing operator, returns
a synonym (i.e., an alias or a nickname) for the object to which its pointer operand points. For instance,
1 printf (”%d\n”, ∗aPtr);
would.
Using * in this manner is called dereferencing a pointer. A dereferenced pointer may also be used on
the left side of an assignment statement, as in
Dr. Raphael Angulu, BCS 111 SCI, MMUST, 2020: Pointers Notes 2
1 float a;
2 float ∗aPtr;
3 aPtr = &a;
4 ∗aPtr = 10;
where line 4 takes the value 10 and store it in a variable a (Take the value 10 and store it in variable whose
address is in *aPtr). You can still read the value from the keyboard as in
1 float a;
2 float ∗aPtr;
3 aPtr = &a;
4 scanf(”%f”, aPtr); //same as scanf(”%d”, &a);
Dereferencing an uninitialized pointer could cause a fatal execution-time error, or it could accidentally
modify important data and allow the program to run to completion, possibly with incorrect results.
R
Example
1 #include <iostream>
LU
2 using namespace std;
3
4 int main(){
5 float a; // a is an integer
6 a = 12.725;
7 float ∗aPtr;
8 aPtr = &a;
U
9 // assigned 7 to a
10 printf (”The address of a is %X”, &a);
11 printf (”\nThe value of aPtr is %X ”, aPtr);
printf (”\n\nThe value of a is %f”, a);
G
12
13 printf (”\nThe value of ∗aPtr is %f”, ∗aPtr);
14 printf (”\n\nShowing that ∗ and & are inverses of each other”);
15 printf (”\n&∗aPtr = %X \n∗&aPtr = %X”, &∗aPtr, ∗&aPtr);
N
16
17 } // end main
Figure 3 shows the output of this code, of course on my system, you may get difference values for references
.A
on your system.
R
D
The & and * operators are inverses of one another. When they are applied consecutively to aPtr in either
order, they cancel one another out yielding the same result (the value in aPtr).
Dr. Raphael Angulu, BCS 111 SCI, MMUST, 2020: Pointers Notes 3
Pointer Arithmetic
Consider the following two lines of code
1 int number = 10;
2 int ∗numPtr = &number;
We can apply +, −, *, \or % operators on the variable number either directly or indirectly through
the pointer *numPtr
as shown below
R
This shows that numPtr is storing the address of number.
LU
Therefore it also follows that the following two lines are identical, they do the same thing,
that is reading an integer from the keyboard and store it in variable number
1 scanf(”%d”, &number);
2 scanf(”%d”, numPtr);
U
Consider the output of the following 2 lines of code
1 printf (”Value stored in number = %d\n”, number);
2 printf (”numPtr points to which value = %d\n”, ∗numPtr);
G
shown below
N
This shows that numPtr actually points (stores the address of) number
.A
Consider the following lines of code. First line adds 1 to the value in number and second
line adds 1 to value in numPtr (address of number )
1 printf (”Increment value in number (number + 1) = %d\n”, number+1);
2 printf (”Increment value in numPtr (numPtr + 1) = %X”, numPtr+1);
R
Note that, new value of number = 11 while new value of numPtr = 62FE18. Remem-
ber, initially numPtr = 62FE14 (see first output above). Adding 1 means adding one block of
memory big enough to hold an integer, on my machine this is 4 bytes thats why the new memory
address is 62FE18 which is 62FE14 + 4.
Adding 1 to a memory address is analogous to telling the computer go to the address 4 bytes
(for this case) away from the current address
Dr. Raphael Angulu, BCS 111 SCI, MMUST, 2020: Pointers Notes 4
Consider the following program on a machine that uses 64 bits to represent doubles
1 #include<stdio.h>
2 int main()
3 {
4 double x = 12.5;
5 double ∗xPtr;
6 xPtr = &x;
7 printf (”%X\n”, &x);
8 printf (”%X\n”, xPtr);
9 printf (”x = %lf\n”, x);
10 printf (”∗xPtr + 2 = %lf\n”, ∗xPtr + 2);
11 printf (”%X\n”, xPtr + 2);
12 printf (”%X\n”, xPtr − 1);
13 }
If line 7 displays 62FE10, what would be the output of lines 8, 9, 10, 11 and 12 [3 Marks]
Output of this code is shown below
R
LU
U
G
N
.A
R
D
Dr. Raphael Angulu, BCS 111 SCI, MMUST, 2020: Pointers Notes 5