Skip to content

Commit 60b18e4

Browse files
authored
Merge pull request #3163 from ntrel/ptr-docs
[arrays.dd] Improve pointer docs Signed-off-by: Dennis <dkorpel@users.noreply.github.com> Merged-on-behalf-of: Dennis <dkorpel@users.noreply.github.com>
2 parents c3cd7f0 + 03622ce commit 60b18e4

File tree

2 files changed

+91
-38
lines changed

2 files changed

+91
-38
lines changed

spec/arrays.dd

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,24 @@ $(H2 $(LNAME2 array-kinds, Kinds))
1818

1919
$(H3 $(LNAME2 pointers, Pointers))
2020

21+
$(P A pointer to type $(D T) has a value which is a reference (address) to another
22+
object of type $(D T). It is commonly called a $(I pointer to T) and its type is
23+
`T*`. To access the object value, use the `*` dereference operator:
24+
)
25+
26+
$(SPEC_RUNNABLE_EXAMPLE_RUN
2127
---------
2228
int* p;
23-
---------
2429

25-
$(P A pointer to type $(I T) has a value which is a reference (address) to another
26-
object of type $(I T). It is commonly called a $(I pointer to T).
27-
)
30+
assert(p == null);
31+
p = new int(5);
32+
assert(p != null);
33+
34+
assert(*p == 5);
35+
(*p)++;
36+
assert(*p == 6);
37+
---------
38+
)
2839

2940
$(P If a pointer contains a $(I null) value, it is not pointing to a valid object.)
3041

@@ -43,13 +54,34 @@ int* p;
4354
to a valid object of type $(I T).)
4455
))
4556

46-
$(BEST_PRACTICE These are simple pointers to data.
47-
Pointers are provided for interfacing with C and for
57+
$(P To set a pointer to point at an existing object, use the
58+
`&` *address of* operator:)
59+
60+
$(SPEC_RUNNABLE_EXAMPLE_RUN
61+
---------
62+
int i = 2;
63+
int* p = &i;
64+
65+
assert(p == &i);
66+
assert(*p == 2);
67+
*p = 4;
68+
assert(i == 4);
69+
---------
70+
)
71+
72+
$(P These are simple pointers to data.
73+
A pointer can manipulate a block of multiple values. Accessing more
74+
than one value cannot be
75+
$(DDLINK spec/memory-safe-d, Memory-Safe-D-Spec, `@safe`) as it
76+
requires $(RELATIVE_LINK2 pointer-arithmetic, pointer arithmetic).
77+
This is supported for interfacing with C and for
4878
specialized systems work.
49-
There is no length associated with it, and so there is no way for the
79+
A pointer has no length associated with it, so there is no way for the
5080
compiler or runtime to do bounds checking, etc., on it.
51-
Most conventional uses for pointers can be replaced with
52-
dynamic arrays, $(D out) and $(D ref) parameters,
81+
)
82+
83+
$(BEST_PRACTICE Most conventional uses for pointers can be replaced with
84+
dynamic arrays, $(D ref) and $(D out) $(DDSUBLINK function, parameters, parameters),
5385
and reference types.
5486
)
5587

@@ -192,6 +224,29 @@ assert(b[1] == 2);
192224

193225
$(P See also $(GLINK2 expression, IndexExpression).)
194226

227+
$(H3 $(LNAME2 pointer-arithmetic, Pointer Arithmetic))
228+
229+
$(P A pointer can also be indexed, but no bounds checks are done.
230+
Unlike arrays, a pointer value can also be used in certain
231+
arithmetic expressions to produce another pointer:)
232+
233+
$(SPEC_RUNNABLE_EXAMPLE_RUN
234+
---
235+
int[] a = [1,2,3];
236+
int* p = a.ptr;
237+
238+
p[2] = 4;
239+
assert(a[2] == 4);
240+
writeln(p[3]); // undefined behaviour
241+
242+
assert(p == &a[0]);
243+
p++; // point to a[1]
244+
assert(*p == 2);
245+
---
246+
)
247+
248+
$(P See $(DDSUBLINK spec/expression, pointer_arithmetic, *AddExpression*) for details.)
249+
195250
$(H2 $(LNAME2 slicing, Slicing))
196251

197252
$(P $(I Slicing) an array means to specify a subarray of it.
@@ -231,12 +286,14 @@ $(SPEC_RUNNABLE_EXAMPLE_RUN
231286
int[10] a = [ 1,2,3,4,5,6,7,8,9,10 ];
232287

233288
int* p = &a[2];
234-
int[] b = p[0..8];
235-
writeln(b);
236289
writeln(p[7]); // 10
237290
writeln(p[8]); // undefined behaviour
291+
292+
int[] b = p[0..8]; // convert pointer elements to dynamic array
293+
assert(b is a[2..10]);
294+
writeln(b);
238295
writeln(b[7]); // 10
239-
//writeln(b[8]); // range error
296+
//writeln(b[8]); // runtime error (unless bounds checks turned off)
240297
---------
241298
)
242299

@@ -452,30 +509,6 @@ a[] -= (b[] + 4) * c[];
452509
the target computer.
453510
)
454511

455-
$(H2 $(LNAME2 pointer-arithmetic, Pointer Arithmetic))
456-
457-
$(SPEC_RUNNABLE_EXAMPLE_FAIL
458-
---------
459-
void dibb(int* array)
460-
{
461-
array[2]; // means same thing as *(array + 2)
462-
*(array + 2); // get 3rd element
463-
}
464-
465-
void diss(int[] array)
466-
{
467-
array[2]; // ok
468-
*(array + 2); // error, array is not a pointer
469-
}
470-
471-
void ditt(int[3] array)
472-
{
473-
array[2]; // ok
474-
*(array + 2); // error, array is not a pointer
475-
}
476-
---------
477-
)
478-
479512
$(H2 $(LNAME2 rectangular-arrays, Rectangular Arrays))
480513

481514
$(P Experienced FORTRAN numerics programmers know that multidimensional

spec/expression.dd

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,20 @@ $(GNAME AddExpression):
817817
the size of the type pointed to by the first operand.
818818
)
819819

820+
$(SPEC_RUNNABLE_EXAMPLE_RUN
821+
---
822+
int[] a = [1,2,3];
823+
int* p = a.ptr;
824+
assert(*p == 1);
825+
826+
*(p + 2) = 4; // same as `p[2] = 4`
827+
assert(a[2] == 4);
828+
---
829+
)
830+
831+
$(P $(GLINK IndexExpression) can also be used with a pointer and has
832+
the same behaviour as adding an integer.)
833+
820834
$(P If the second operand is a pointer, and the first is an integral type,
821835
and the operator is $(D +),
822836
the operands are reversed and the pointer arithmetic just described
@@ -835,7 +849,13 @@ $(GNAME AddExpression):
835849
The type of the result is $(D ptrdiff_t).
836850
)
837851

838-
$(P $(GLINK IndexExpression) can also be used with a pointer.)
852+
$(SPEC_RUNNABLE_EXAMPLE_RUN
853+
---
854+
int[] a = [1,2,3];
855+
ptrdiff_t d = &a[2] - a.ptr;
856+
assert(d == 2);
857+
---
858+
)
839859

840860
$(H2 $(LNAME2 cat_expressions, Cat Expressions))
841861

@@ -924,7 +944,7 @@ $(GNAME UnaryExpression):
924944

925945
$(TABLE
926946
$(THEAD Operator, Description)
927-
$(TROW `&`, Take memory address of an $(RELATIVE_LINK2 .define-lvalue, lvalue) - see $(DDSUBLINK arrays, pointer, pointers))
947+
$(TROW `&`, Take memory address of an $(RELATIVE_LINK2 .define-lvalue, lvalue) - see $(DDSUBLINK arrays, pointers, pointers))
928948
$(TROW `++`, Increment before use - see $(RELATIVE_LINK2 order-of-evaluation, order of evaluation))
929949
$(TROW `--`, Decrement before use)
930950
$(TROW `*`, Dereference/indirection - typically for pointers)

0 commit comments

Comments
 (0)