Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Introduction To Pointers-1

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 7

1.

Introduction to pointers
A variable is a name for a piece of memory that holds a value. When our program instantiates a
variable, a free memory address is automatically assigned to the variable, and any value we
assign to the variable is stored in this memory address.
For example:
int x;
When this statement is executed by the CPU, a piece of memory from RAM will be set aside.
For the sake of example, let’s say that the variable x is assigned memory location 140. Whenever
the program sees the variable x in an expression or statement, it knows that it should look in
memory location 140 to get the value.
The nice thing about variables is that we don’t need to worry about what specific memory
address is assigned. We just refer to the variable by its given identifier, and the compiler
translates this name into the appropriately assigned memory address.
a. The address-of operator (&)
The address-of operator (&) allows us to see what memory address is assigned to a variable. This
is pretty straightforward:
#include <iostream>
 
int main()
{
    int x = 5;
    std::cout << x << '\n'; // print the value of variable x
    std::cout << &x << '\n'; // print the memory address of variable x
 
    return 0;
}
On the author’s machine, the above program printed:
5
0027FEA0
Note: Although the address-of operator looks just like the bitwise-and operator, you can
distinguish them because the address-of operator is unary, whereas the bitwise-and operator is
binary.
b. The dereference operator (*)
The dereference operator (*) allows us to get the value at a particular address:
#include <iostream>
int main()
{
    int x = 5;
    std::cout << x << '\n'; // print the value of variable x
    std::cout << &x << '\n'; // print the memory address of variable x
    std::cout << *&x << '\n'; /// print the value at the memory address of variable x
 
    return 0;
}
On the author’s machine, the above program printed:
5
0027FEA0
5
2. Pointers
With the address-of operator and dereference operators now added to our toolkits, we can now
talk about pointers. A pointer is a variable that holds a memory address as its value.
a. Declaring a pointer
Pointer variables are declared just like normal variable, only with an asterisk between the data
type and the variable name:
int *iPtr; // a pointer to an integer value
double *dPtr; // a pointer to a double value
int* iPtr2; // also valid syntax (acceptable, but not favored)
int * iPtr3; // also valid syntax (but don't do this)
int *iPtr4, *iPtr5; // declare two pointers to integer variables
Note: that the asterisk here is not a dereference. It is part of the pointer declaration syntax.
Syntactically, C++ will accept the asterisk next to the data type, next to the variable name, or
even in the middle.
However, when declaring multiple pointer variables, the asterisk has to be included with each
variable. It’s easy to forget to do this if you get used to attaching the asterisk to the type instead
of the variable name!
int* iPtr6, iPtr7; // iPtr6 is a pointer to an int, but iPtr7 is just a plain int!
For this reason, when declaring a variable, we recommend putting the asterisk next to the
variable name.
Best practice: When declaring a pointer variable, put the asterisk next to the variable name.
However, when returning a pointer from a function, it’s clearer to put the asterisk next to the
return type:
int* doSomething();
This makes it clear that the function is returning a value of type int* and not an int.
Best practice: When declaring a function, put the asterisk of a pointer return value next to the
type.
Just like normal variables, pointers are not initialized when declared. If not initialized with a
value, they will contain garbage.
b. Assigning a value to a pointer
Since pointers only hold addresses, when we assign a value to a pointer, that value has to be an
address. One of the most common things to do with pointers is have them hold the address of
another variable.
To get the address of a variable, we use the address-of operator:
int value = 5;
int *ptr = &value; // assign address of variable value to ptr
Conceptually, you can think of the above snippet like this:

This is where pointers get their name from -- ptr is holding the address of variable value, so we
say that ptr is “pointing to” value.
It is also easy to see using code:
#include <iostream>
 
int main()
{
    int value = 5;
    int *ptr = &value; // assign address of value to ptr
 
    std::cout << &value << endl; // print the address of variable value
    std::cout << ptr << endl; // print the address that ptr is holding
 
    return 0;
}
On the author’s machine, this printed:
0012FF7C
0012FF7C
The type of the pointer has to match the type of the variable being pointed to:
int iValue = 5;
double dValue = 7.0;

int *iPtr = &iValue; // ok


double *dPtr = &dValue; // ok
iPtr = &dValue; // wrong -- int pointer cannot point to the address of a double variable
dPtr = &iValue; // wrong -- double pointer cannot point to the address of an int variable
Note that the following is also not legal:
int *ptr = 5;
This is because pointers can only hold addresses, and the integer literal 5 does not have a
memory address. If you try this, the compiler will tell you it cannot convert an integer to an
integer pointer.
C++ will also not allow you to directly assign literal memory addresses to a pointer:
double *dPtr = 0012FF7C; // not okay, treated as assigning an integer literal
c. The address-of operator returns a pointer
It’s worth noting that the address-of operator (&) doesn’t return the address of its operand as a
literal. Instead, it returns a pointer containing the address of the operand, whose type is derived
from the argument (e.g. taking the address of an int will return the address in an int pointer).
We can see this in the following example:
#include <iostream>
int main()
{
int x(4);
std::cout << &x;
 
return 0;
}
It prints:

This pointer can then be printed or assigned as desired.


Dereferencing pointers
Once we have a pointer variable pointing at something, the other common thing to do with it is
dereference the pointer to get the value of what it’s pointing at. A dereferenced pointer evaluates
to the contents of the address it is pointing to.
int value = 5;
std::cout << &value; // prints address of value
std::cout << value; // prints contents of value
 
int *ptr = &value; // ptr points to value
std::cout << ptr; // prints address held in ptr, which is &value
std::cout << *ptr; // dereference ptr (get the value that ptr is pointing to)
The above program prints:
0012FF7C
5
0012FF7C
5
This is why pointers must have a type. Without a type, a pointer wouldn’t know how to interpret
the contents it was pointing to when it was dereferenced. It’s also why the type of the pointer and
the variable address it’s being assigned to must match. If they did not, when the pointer was
dereferenced, it would misinterpret the bits as a different type.
Once assigned, a pointer value can be reassigned to another value:
int value1 = 5;
int value2 = 7;
 int *ptr;
 ptr = &value1; // ptr points to value1
std::cout << *ptr; // prints 5
 ptr = &value2; // ptr now points to value2
std::cout << *ptr; // prints 7
Note that when the address of variable value is assigned to ptr:
 ptr is the same as &value
 *ptr is treated the same as value
Because *ptr is treated the same as value, you can assign values to it just as if it were variable
value! The following program prints 7:
int value = 5;
int *ptr = &value; // ptr points to value
 
*ptr = 7; // *ptr is the same as value, which is assigned 7
std::cout << value; // prints 7

You might also like