-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpointers.wil
139 lines (107 loc) · 3.2 KB
/
pointers.wil
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
In Wilfrid, you have direct access to the memory
and can manipulate it freely with pointers.
The results of pointer operations are not checked.
With great freedom comes great responsibility - Wilfrid
isn't a memory-safe language by choice.
If you prefer automatic memory management, Wilfrid
also offers optional garbage collection;
see the "Memory management" example.
*/
fn main()
{
/*
To declare a pointer, use a type name and a caret sign:
*/
let ptr : int^
/*
To take an address of something, use the at sign:
*/
let some_int = 3
ptr = @some_int
/*
To dereference a pointer, i. e. take a value
that is pointed to by it, use the hash sign:
*/
let some_int_copy = #ptr
if (some_int_copy == some_int)
{
printf("some_int and some_int_copy are the same\\n")
}
/*
Let's use pointer arithmetic to traverse an array.
First, we declare an array with initial values and take
a pointer to its beginning.
*/
let array : int[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
let first_number = @array as int^
/*
Let's use the for loop:
*/
for (let offset := 0, offset < 10, offset++)
{
/*
With each iteration of the loop, we increase the offset
by one. We add it to the pointer to the first number
and then dereference it. This way each iteration
of the loop we are one element in the array further.
*/
let number := #(first_number + offset)
/*
As we can see, pointer arithmetic moves a pointer
by a multiple of the size of a type that is pointed
to by it.
Adding one to a pointer to a char moves us one byte,
because a char is one byte long.
Adding one to a pointer to a long integer moves us
by eight bytes, because that's the size of a long integer.
*/
printf("Number is %d\\n", number)
}
/*
An alternative version of the same operation, this
time performing pointer arithmetic in the for loop
statement itself:
*/
for (let num_ptr := first_number,
num_ptr < first_number + 10,
num_ptr++)
{
let number = #num_ptr
printf("Number is %d\\n", number)
}
/*
Pointers cannot be added together.
They can, however, be subtracted:
*/
let diff := @some_int - @some_int_copy
printf("The difference between %p and %p is: %lld\\n",
@some_int, @some_int_copy, diff)
/*
A result of subtracting pointers is always a long integer.
*/
/*
If a pointer points to a struct, there is no need
to dereference it before accessing the struct's fields.
The same goes for unions. The dot operator automatically
performs dereference. An example:
*/
let some_struct : test_struct = { int_field = 10 }
let ptr_to_struct = @some_struct
printf("The value of the field is: %d\\n", ptr_to_struct.int_field)
/*
This works no matter how many layers of indirection
there are:
*/
let ptr_to_ptr = @ptr_to_struct
let meta_ptr = @ptr_to_ptr
printf("The value of the field is: %d\\n", meta_ptr.int_field)
/*
For a more advanced example of pointers usage, see
the "Memory arena" example.
*/
}
struct test_struct
{
int_field: int
}