Pointers
A pointer is a variable whose value is the address of some value.
The declaration looks as follows:
The pointer is defined by the type of the value that it points to. This is helpful, because:
- we can do various arithmetic operations on pointers (e.g.
++
will result in the correct amount of bytes being added). - we can dereference pointers - the runtime needs to know how many bytes a given
pointer points to and how to interpret them (e.g.
int
andfloat
both take 4 bytes, but the same contents mean different values)
The “star” sign may be placed adjacent to the type, or to the name, or both:
Use-cases
Pointers are useful for:
- passing data to functions by reference (e.g.
void increment(int *number)
) - allocating memory on the heap and keeping reference to it
Memory
Memory is organized as follows:
Each slot is addressed.
A pointer stores an address to some value in memory:
The pointer itself also has an address in memory, it also is some variable.
In the case above, &p
is 64
.
Variables
When we define some variable, it will be assigned some address in memory. If we try to print the value under that address, we will find some “random” data:
Usage
Arrays
An array can be treated as a pointer to the first element that it contains.
Simply:
- address:
&array[i]
=array + i
=pointer + i
; - value:
array[i]
=*(array + i)
=*(pointer + i)
Multi-dimensional Arrays
Pointer arithmetic examples:
- Printing
B
(or&B[0]
) would return400
(the address of the first sub-array) - Printing
*B
(orB[0]
or&B[0][0]
) would return400
(the address of the first element in the first sub-array) - Printing
B+1
(or&B[1]
) would return412
(the address of the second sub-array) - Printing
*(B+1)
(orB[1]
or&B[1][0]
) would return412
(the address of the first element in the second sub-array) - Printing
*(*B+1)
(orB[0][1]
) would return3
. p++
would move from400
to412
Pointer to Pointer
A p
points to x
. q
points to p
.
In this example, we have even int ***
pointer (a pointer to pointer to pointer).
We can also dereference such “deep” pointers. For example:
Arrays as arguments
When a function accepts an array as an argument, a pointer to an array is passed:
This means that sizeof(A)
will be different in main()
(20 bytes) and in
SumOfElements()
(4 bytes - just the size of a pointer to an integer!).
Returning a pointer
It’s wrong to return a pointer to a variable on a stack:
Instead, we should allocate the result on the heap and return a pointer to it.
Function Pointers
A pointer p
points to a function Add
.