Skip to content

Commit 46f93c0

Browse files
authored
feat: add pointers concept (#823)
* feat: add pointers concept
1 parent d592d89 commit 46f93c0

File tree

5 files changed

+256
-2
lines changed

5 files changed

+256
-2
lines changed

concepts/pointers/.meta/config.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"blurb": "In C++, pointers are variables that store object addresses. They allow you to directly manipulate memory and access to data structures like arrays and objects.",
3+
"authors": [
4+
"vaeng"
5+
]
6+
}

concepts/pointers/about.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# Introduction
2+
3+
Like many other languages, C++ has _pointers_.
4+
You already know _references_ and _pointers_ are similar, but think of them as a level closer to the inner workings of your computer.
5+
_Pointers_ are variables that hold object addresses.
6+
They are used to directly interact with objects, enabling dynamic memory allocation and efficient data manipulation in C++.
7+
8+
If you're new to _pointers_, they can feel a little mysterious but once you get used to them, they're quite straight-forward.
9+
10+
They're a crucial part of C++, so take some time to really understand them.
11+
The bare-bone version in this concept is also called _dumb pointer_ or _raw pointer_.
12+
With modern C++ there are also _smart pointers_, the basic type is not smart at all and you have to handle all the work manually.
13+
14+
Before digging into the details, it's worth understanding the use of _pointers_.
15+
_Pointers_ are a way to share an object's address with other parts of our program, which is useful for two major reasons:
16+
1. Like _references_, pointers avoid copies and help to reduce the resource-footprint of your program.
17+
2. Unlike _references_, pointers can be reassigned to different objects.
18+
3. Pointers can also point to a null value, to indicate, that they currently do not point to any object.
19+
20+
## General Syntax
21+
22+
A pointer declaration in C++ involves specifying the data type to which the the pointer is pointing, followed by an asterisk (`*`) and the pointer's name.
23+
When pointers are declared, they are not automatically initialized.
24+
Without explicit assignment, a pointer typically holds an indeterminate value, often referred to as a "garbage address."
25+
While certain compilers might initialize pointers to `nullptr`, this behavior is not guaranteed across all compilers, so it's essential not to rely on it.
26+
It's best practice to explicitly initialize raw pointers and verify their non-null status before utilization to avoid potential issues.
27+
28+
```cpp
29+
int* ptr{nullptr}; // Declares a pointer and makes sure it is not invalid
30+
```
31+
32+
To assign the address of a variable to a pointer, you use the address-of operator (`&`).
33+
Dereferencing a pointer is done using the _indirection operator_ (`*`) operator.
34+
35+
```cpp
36+
std::string opponent{"Solomon Lane"};
37+
// 'ethan' points to the address of the string opponent
38+
std::string* ethan{&opponent};
39+
// Instead of ethan's, the opponent's name address is given to the passPort
40+
std::string passportName{*ethan};
41+
```
42+
43+
Attention: dereferencing has to be done explicitly, while _references_ just worked like an alias.
44+
45+
## Pointer Arithmetic
46+
47+
_Pointer arithmetic_ allows you to perform arithmetic operations on pointers, which is particularly useful when working with arrays.
48+
Adding an integer to a pointer makes it point to a different element.
49+
50+
```cpp
51+
// Stargate addresses
52+
int gateAddresses[] = {462, 753, 218, 611, 977};
53+
// 'ptr' points to the first element of 'gateAddresses'
54+
int* ptr{gateAddresses};
55+
// Accesses the third Stargate address through pointer arithmetic
56+
int dialedAddress{*(ptr + 2)};
57+
// Chevron encoded! Dialing Stargate address:
58+
openStarGate(dialedAddress);
59+
```
60+
61+
~~~~exercism/caution
62+
Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully.
63+
Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities.
64+
One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure.
65+
~~~~
66+
67+
## Accessing member variables
68+
69+
In C++, the `->` operator is used to access members of an object through a pointer to that object.
70+
It is a shorthand which simplifies accessing members of objects pointed to by pointers.
71+
For instance, if `ptr` is a pointer to an object with a member variable `x`, instead of using `(*ptr).x`, you can directly use `ptr->x`.
72+
This operator enhances code readability and reduces verbosity when working with pointers to objects.
73+
74+
Here's a brief example, with a _struct_ `Superhero` that has a member variable `superpower`.
75+
The main function creates a pointer `dianaPrince` to a `Superhero` object (representing Wonder Woman).
76+
The `->` operator is used to access the member variable `superpower`, showcasing Wonder Woman's iconic "Lasso of Truth."
77+
78+
```cpp
79+
struct Superhero {
80+
std::string superpower;
81+
};
82+
83+
Superhero* dianaPrince = new Superhero;
84+
dianaPrince->superpower = "Lasso of Truth";
85+
// Using the -> operator to access member variable superpower:
86+
std::cout << "Wonder Woman, possesses the mighty " << dianaPrince->superpower;
87+
// Memory cleanup:
88+
delete dianaPrince;
89+
```
90+
91+
## Pointers vs. references
92+
93+
Pointers and references both enable indirect access to objects, but they differ in their capabilities and safety considerations.
94+
Pointers offer the flexibility of changing their target object and can be assigned null.
95+
However, this flexibility introduces risks, such as dereferencing null pointers or creating dangling pointers.
96+
References, on the other hand, cannot be null and are bound to valid objects upon creation, avoiding these risks.
97+
Given their safer nature, references should be preferred over pointers unless the additional functionalities provided by pointers are necessary.
98+
99+
~~~~exercism/advanced
100+
## Dynamic Memory Allocation and Null Pointers
101+
102+
In C++, `new` is used to dynamically allocate memory for objects on the heap during runtime.
103+
It returns a pointer to the allocated memory address, allowing objects to have lifetimes not tied to a specific scope.
104+
However, it's important to always pair `new` with `delete` to properly deallocate memory.
105+
Dynamic memory allocation should be used cautiously to prevent common issues like memory leaks and accessing deallocated memory.
106+
107+
Pointers can also be set to a special value called a _null pointer_, which indicates that they do not point to a valid address.
108+
Null pointers are commonly used to initialize pointers before assigning them to valid values.
109+
110+
```cpp
111+
// There is a dark mark bearer, but who is it?
112+
std::string* darkMarkBearer{nullptr};
113+
// It is Bellatrix!
114+
darkMarkBearer = new std::string{"Bellatrix Lestrange"};
115+
// She has been defeated
116+
delete darkMarkBearer;
117+
// Reset pointer to null, symbolizing there is no more darkMarkBearer at the moment
118+
darkMarkBearer = nullptr;
119+
```
120+
121+
A pointer should either hold the address of a valid object, or be set to `nullptr`.
122+
That way you only need to test pointers for null, and can assume any non-null pointer is valid.
123+
When an object is destroyed, any pointers to the destroyed object will be left _dangling_ (they will not be automatically set to `nullptr`).
124+
It is your responsibility to detect these cases and ensure those pointers are subsequently set to `nullptr`.
125+
126+
127+
In older code, you might encounter two alternatives to `nullptr`.
128+
Firstly, the literal `0` is specifically interpreted as a null value for pointers, though it's the only scenario where an integral literal can be assigned to a pointer.
129+
Secondly, the `preprocessor macro` `NULL`, inherited from C and defined in the `<cstddef>` header, is another representation of a null pointer, though its usage is less common in modern C++ code.
130+
~~~~
131+
132+
[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88

concepts/pointers/introduction.md

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# Introduction
2+
3+
Like many other languages, C++ has _pointers_.
4+
You already know _references_ and _pointers_ are similar, but think of them as a level closer to the inner workings of your computer.
5+
_Pointers_ are variables that hold object addresses.
6+
They are used to directly interact with objects, enabling dynamic memory allocation and efficient data manipulation in C++.
7+
8+
If you're new to _pointers_, they can feel a little mysterious but once you get used to them, they're quite straight-forward.
9+
10+
They're a crucial part of C++, so take some time to really understand them.
11+
The bare-bone version in this concept is also called _dumb pointer_ or _raw pointer_.
12+
With modern C++ there are also _smart pointers_, the basic type is not smart at all and you have to handle all the work manually.
13+
14+
Before digging into the details, it's worth understanding the use of _pointers_.
15+
_Pointers_ are a way to share an object's address with other parts of our program, which is useful for two major reasons:
16+
1. Like _references_, pointers avoid copies and help to reduce the resource-footprint of your program.
17+
2. Unlike _references_, pointers can be reassigned to different objects.
18+
3. Pointers can also point to a null value, to indicate, that they currently do not point to any object.
19+
20+
## General Syntax
21+
22+
A pointer declaration in C++ involves specifying the data type to which the the pointer is pointing, followed by an asterisk (`*`) and the pointer's name.
23+
When pointers are declared, they are not automatically initialized.
24+
Without explicit assignment, a pointer typically holds an indeterminate value, often referred to as a "garbage address."
25+
While certain compilers might initialize pointers to `nullptr`, this behavior is not guaranteed across all compilers, so it's essential not to rely on it.
26+
It's best practice to explicitly initialize raw pointers and verify their non-null status before utilization to avoid potential issues.
27+
28+
```cpp
29+
int* ptr{nullptr}; // Declares a pointer and makes sure it is not invalid
30+
```
31+
32+
To assign the address of a variable to a pointer, you use the address-of operator (`&`).
33+
Dereferencing a pointer is done using the _indirection operator_ (`*`) operator.
34+
35+
```cpp
36+
std::string opponent{"Solomon Lane"};
37+
// 'ethan' points to the address of the string opponent
38+
std::string* ethan{&opponent};
39+
// Instead of ethan's, the opponent's name address is given to the passPort
40+
std::string passportName{*ethan};
41+
```
42+
43+
Attention: dereferencing has to be done explicitly, while _references_ just worked like an alias.
44+
45+
## Pointer Arithmetic
46+
47+
_Pointer arithmetic_ allows you to perform arithmetic operations on pointers, which is particularly useful when working with arrays.
48+
Adding an integer to a pointer makes it point to a different element.
49+
50+
```cpp
51+
// Stargate addresses
52+
int gateAddresses[] = {462, 753, 218, 611, 977};
53+
// 'ptr' points to the first element of 'gateAddresses'
54+
int* ptr{gateAddresses};
55+
// Accesses the third Stargate address through pointer arithmetic
56+
int dialedAddress{*(ptr + 2)};
57+
// Chevron encoded! Dialing Stargate address:
58+
openStarGate(dialedAddress);
59+
```
60+
61+
~~~~exercism/caution
62+
Pointer arithmetic in C++ can easily lead to __undefined behavior__ if not handled carefully.
63+
Undefined behavior can manifest in unexpected program outcomes, crashes, or even security vulnerabilities.
64+
One infamous example of the consequences of undefined behavior occurred in the [explosion of the Ariane 5 rocket][ariane-flight-v88] in 1996, where a software exception caused by the conversion of a 64-bit floating-point number to a 16-bit signed integer led to a catastrophic failure.
65+
~~~~
66+
67+
## Accessing member variables
68+
69+
In C++, the `->` operator is used to access members of an object through a pointer to that object.
70+
It is a shorthand which simplifies accessing members of objects pointed to by pointers.
71+
For instance, if `ptr` is a pointer to an object with a member variable `x`, instead of using `(*ptr).x`, you can directly use `ptr->x`.
72+
This operator enhances code readability and reduces verbosity when working with pointers to objects.
73+
74+
Here's a brief example, with a _struct_ `Superhero` that has a member variable `superpower`.
75+
The main function creates a pointer `dianaPrince` to a `Superhero` object (representing Wonder Woman).
76+
The `->` operator is used to access the member variable `superpower`, showcasing Wonder Woman's iconic "Lasso of Truth."
77+
78+
```cpp
79+
struct Superhero {
80+
std::string superpower;
81+
};
82+
83+
Superhero* dianaPrince = new Superhero;
84+
dianaPrince->superpower = "Lasso of Truth";
85+
// Using the -> operator to access member variable superpower:
86+
std::cout << "Wonder Woman, possesses the mighty " << dianaPrince->superpower;
87+
// Memory cleanup:
88+
delete dianaPrince;
89+
```
90+
91+
## Pointers vs. references
92+
93+
Pointers and references both enable indirect access to objects, but they differ in their capabilities and safety considerations.
94+
Pointers offer the flexibility of changing their target object and can be assigned null.
95+
However, this flexibility introduces risks, such as dereferencing null pointers or creating dangling pointers.
96+
References, on the other hand, cannot be null and are bound to valid objects upon creation, avoiding these risks.
97+
Given their safer nature, references should be preferred over pointers unless the additional functionalities provided by pointers are necessary.
98+
99+
[ariane-flight-v88]: https://en.wikipedia.org/wiki/Ariane_flight_V88

concepts/pointers/links.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"url": "https://en.cppreference.com/w/c/language/pointer",
4+
"description": "C++ reference on pointers"
5+
},
6+
{
7+
"url": "https://en.cppreference.com/w/cpp/memory/new",
8+
"description": "C++ reference on dynamic memory allocation with new"
9+
},
10+
{
11+
"url": "https://en.cppreference.com/w/cpp/language/delete",
12+
"description": "C++ reference on dynamic memory deallocation with delete"
13+
}
14+
]

config.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,8 +1215,6 @@
12151215
"prerequisites": [
12161216
"basics",
12171217
"namespaces",
1218-
"conditionals",
1219-
"lists",
12201218
"loops",
12211219
"numbers",
12221220
"strings"
@@ -1309,6 +1307,11 @@
13091307
"slug": "functions",
13101308
"name": "Functions"
13111309
},
1310+
{
1311+
"uuid": "c071a5e8-796c-4538-945a-3bdd2006fc2b",
1312+
"slug": "pointers",
1313+
"name": "Pointers"
1314+
},
13121315
{
13131316
"uuid": "0316eb64-d1e9-44cc-b7d4-ea4b88f85ac3",
13141317
"slug": "smart-pointers",

0 commit comments

Comments
 (0)