Skip to content

Commit 412771e

Browse files
author
mikeblome
committed
added example
1 parent c3362dc commit 412771e

File tree

1 file changed

+152
-26
lines changed

1 file changed

+152
-26
lines changed

docs/cpp/pointers-cpp.md

Lines changed: 152 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Pointers (C++)"
3-
ms.date: "11/06/2019"
3+
ms.date: "11/07/2019"
44
helpviewer_keywords: ["declarators, pointers", "declarations, pointers", "pointers [C++]", "pointers, declarations"]
55
ms.assetid: 595387c5-8e58-4670-848f-344c7caf985e
66
---
@@ -10,8 +10,21 @@ A pointer stores the address of a object in memory and is used to access that ob
1010

1111
Pointers are used extensively in C++ to pass larger objects to and from functions because it is far more efficient to copy a 64-bit value than to copy an entire object. When a program allocates a new object on the [heap]() in memory, it receives the address of that object in the form of a pointer. Such pointers are called *owning pointers* because they must be used to explicitly delete the object when it is no longer needed. Pointers to functions enable functions to be passed to other functions and are used for "callbacks" in C-style programming.
1212

13+
deferencing
14+
15+
char* p ="Hello";
16+
17+
print p vs. *p
18+
1319
In C and C++, pointer errors are by far the greatest cause of crashes, hangs, data corruption, security holes and general programmer misery. In modern C++, the use of *raw pointers* is strongly discouraged except in very specific scenarios. Modern C++ provides *smart pointers* for allocating objects, *iterators* for traversing data structures, and *lambda expressions* for passing callable functions. By using these language and library facilities instead of raw pointers, you will make your program safer, easier to debug, and simpler to understand and maintain.
1420

21+
## Syntax
22+
23+
```cpp
24+
MyClass* p;
25+
26+
```
27+
1528
## Initialization and member access
1629

1730
The following example shows how to declare a pointer and initialize it with an object allocated on the heap, and then how to use it. It also shows a few of the dangers associated with pointers.
@@ -94,12 +107,75 @@ A const pointer can point to either a const or non-const object, but can't be mo
94107
95108
## Pointer arithmetic
96109
110+
Certain arithmetic operations can be performed on non-const pointers to make them point to a new memory location. A pointer can be incremented and decremented using the **++**, **+=**, **-=** and **--** operators. This technique can be used in arrays and is especially useful in buffers of untyped data. A **void\*** increments by the size of a **char** (1 byte). A typed pointer increments by size of the type it points to.
97111
112+
```cpp
113+
// pointers.cpp : This file contains the 'main' function. Program execution begins and ends there.
114+
//
115+
116+
// Pointer arithmetic may be done with an array declared
117+
// on the stack or allocated on the heap with new.
118+
// The increment operator takes into account the size
119+
// of the objects pointed to.
120+
p = new int[5];
121+
for (i = 0; i < 5; i++, p++) {
122+
*p = i * 10;
123+
printf_s("0x%p %d\n", p, *p);
124+
}
125+
126+
// A common expression seen is dereferencing in combination
127+
// with increment or decrement operators, as shown here.
128+
// The indirection operator * takes precedence over the
129+
// increment operator ++.
130+
// These are particularly useful in manipulating char arrays.
131+
char s1[4] = "cat";
132+
char s2[4] = "dog";
133+
char* p1 = s1;
134+
char* p2 = s2;
135+
136+
// the following is a string copy operation
137+
while (*p1++ = *p2++);
138+
139+
// s2 was copied into s1, so now they are both equal to "dog"
140+
printf_s("%s %s", s1, s2);
141+
142+
#include <iostream>
143+
#include <string>
144+
145+
using namespace std;
146+
147+
class MyClass
148+
{
149+
public:
150+
int num;
151+
std::string name;
152+
void print() { std::cout << name << ":" << num << std::endl; }
153+
};
154+
155+
int main()
156+
{
157+
MyClass arr[3];
158+
arr[0] = {108, "Mike"};
159+
arr[1] = {109, "Lisa"};
160+
arr[2] = {110, "Tabby"};
161+
162+
MyClass* pmc = &arr[0];
163+
cout << pmc->name;
164+
pmc++;
165+
cout << pmc->name;
166+
pmc++;
167+
cout << pmc->name;
168+
}
169+
170+
```
98171

99172
## void* pointers
100173

174+
A pointer to **void** simply points to a raw memory location. Sometimes it is unfortunately necessary to cast a typed pointer to **void\***, for example when passing a pointer to a C++ class object to a C function. The contents of the memory location are not changed, but the type information is lost, so that you cannot perform increment or decrement operations. A memory location can be cast from MyClass* to void* and back again to MyClass* although such operations are inherently error-prone. Modern C++ discourages the use of void pointers unless absolutely necessary.
175+
101176
## Pointers to functions
102177

178+
TBD
103179

104180
> \[*storage-class-specifiers*] \[*cv-qualifiers*] *type-specifiers* \[*ms-modifier*] *declarator* **;**
105181
@@ -173,7 +249,7 @@ int main() {
173249

174250
// a pointer may be assigned to "point to" the value of
175251
// another variable using the & (address of) operator
176-
p = & j;
252+
p = &j;
177253

178254
// since j was on the stack, this address will be somewhere
179255
// on the stack. Pointers are printed in hex format using
@@ -209,31 +285,7 @@ int main() {
209285
// At this point, dereferencing p with *p would trigger
210286
// a runtime access violation.
211287

212-
// Pointer arithmetic may be done with an array declared
213-
// on the stack or allocated on the heap with new.
214-
// The increment operator takes into account the size
215-
// of the objects pointed to.
216-
p = new int[5];
217-
for (i = 0; i < 5; i++, p++) {
218-
*p = i * 10;
219-
printf_s("0x%p %d\n", p, *p);
220-
}
221-
222-
// A common expression seen is dereferencing in combination
223-
// with increment or decrement operators, as shown here.
224-
// The indirection operator * takes precedence over the
225-
// increment operator ++.
226-
// These are particularly useful in manipulating char arrays.
227-
char s1[4] = "cat";
228-
char s2[4] = "dog";
229-
char* p1 = s1;
230-
char* p2 = s2;
231-
232-
// the following is a string copy operation
233-
while (*p1++ = *p2++);
234288

235-
// s2 was copied into s1, so now they are both equal to "dog"
236-
printf_s("%s %s", s1, s2);
237289
}
238290
```
239291

@@ -332,6 +384,80 @@ node 2 = 789
332384
a (add node) d (display list) q (quit)
333385
```
334386

387+
## Example
388+
389+
```cpp
390+
// pointer_arithmetic.cpp : This file contains the 'main' function. Program execution begins and ends there.
391+
//
392+
393+
#include <iostream>
394+
#include <string>
395+
#include <Windows.h>
396+
#include <ostream>
397+
#include <fstream>
398+
399+
using namespace std;
400+
401+
int main()
402+
{
403+
404+
BITMAPINFOHEADER header;
405+
header.biHeight = 100;
406+
header.biWidth = 100;
407+
header.biBitCount = 24;
408+
header.biPlanes = 1;
409+
header.biCompression = BI_RGB;
410+
header.biSize = sizeof(BITMAPINFOHEADER);
411+
412+
constexpr int bufferSize = 30000;
413+
unsigned char* buffer = new unsigned char[bufferSize];
414+
415+
BITMAPFILEHEADER bf;
416+
bf.bfType = 0x4D42;
417+
bf.bfSize = header.biSize + 14 + bufferSize;
418+
bf.bfReserved1 = 0;
419+
bf.bfReserved2 = 0;
420+
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); //54
421+
422+
423+
// Create a gray square with a 2-pixel wide outline
424+
unsigned char* begin = &buffer[0];
425+
unsigned char* end = &buffer[0] + bufferSize;
426+
unsigned char* p = begin;
427+
constexpr int pixelWidth = 3;
428+
constexpr int borderWidth = 2;
429+
430+
int c = 0;
431+
while (p < end)
432+
{
433+
// is top or bottom row:
434+
if ((p < begin + header.biWidth * pixelWidth * borderWidth)
435+
|| (p > end - header.biWidth * pixelWidth * borderWidth)
436+
// is left or right edge:
437+
|| (p - begin) % (header.biWidth * pixelWidth) < (borderWidth * pixelWidth)
438+
|| (p - begin) % (header.biWidth * pixelWidth) > ((header.biWidth - borderWidth) * pixelWidth))
439+
{
440+
*p = 0x0;
441+
}
442+
else
443+
{
444+
*p = 0xC3;
445+
}
446+
p++; //increment one byte (char)
447+
c++;
448+
}
449+
450+
cout << "c = " << c;
451+
ofstream wf(R"(box.bmp)", ios::out | ios::binary);
452+
453+
wf.write(reinterpret_cast<char*>(&bf), sizeof(bf));
454+
wf.write(reinterpret_cast<char*>(&header), sizeof(header));
455+
wf.write(reinterpret_cast<char*>(begin), bufferSize);
456+
delete[] buffer;
457+
wf.close();
458+
}
459+
```
460+
335461
## See also
336462

337463
[Indirection Operator: *](../cpp/indirection-operator-star.md)<br/>

0 commit comments

Comments
 (0)