Pointer
struct Pointer(T)
Overview
A typed pointer to some memory.
This is the only unsafe type in Crystal. If you are using a pointer, you are writing unsafe code because a pointer doesn't know where it's pointing to nor how much memory starting from it is valid. However, pointers make it possible to interface with C and to implement efficient data structures. For example, both Array
and Hash
are implemented using pointers.
You can obtain pointers in four ways: #new
, #malloc
, pointerof
and by calling a C function that returns a pointer.
pointerof(x)
, where x is a variable or an instance variable, returns a pointer to that variable:
x = 1 ptr = pointerof(x) ptr.value = 2 x # => 2
Note that a pointer is falsey if it's null (if it's address is zero).
When calling a C function that expects a pointer you can also pass nil
instead of using Pointer.null
to construct a null pointer.
For a safe alternative, see Slice
, which is a pointer with a size and with bounds checking.
Included Modules
Defined in:
pointer.crprimitives.cr
Class Method Summary
- .malloc(size : Int, value : T)
Allocates
size * sizeof(T)
bytes from the system's heap initialized to value and returns a pointer to the first byte from that memory. - .malloc(size : UInt64)
Allocates
size * sizeof(T)
bytes from the system's heap initialized to zero and returns a pointer to the first byte from that memory. - .malloc(size : Int = 1)
Allocates
size * sizeof(T)
bytes from the system's heap initialized to zero and returns a pointer to the first byte from that memory. - .malloc(size : Int, &block : Int32 -> T)
Allocates
size * sizeof(T)
bytes from the system's heap initialized to the value returned by the block (which is invoked once with each index in the range0...size
) and returns a pointer to the first byte from that memory. - .new(address : UInt64)
Returns a pointer that points to the given memory address.
- .new(address : Int)
Returns a pointer that points to the given memory address.
- .new
- .null
Returns a pointer whose memory address is zero.
Instance Method Summary
- #+(offset : Int64) : self
Returns a new pointer whose address is this pointer's address incremented by
other * sizeof(T)
. - #+(other : Int)
Returns a new pointer whose address is this pointer's address incremented by
other * sizeof(T)
. - #-(other : Int)
Returns a new pointer whose address is this pointer's address decremented by
other * sizeof(T)
. - #-(other : self) : Int64
Returns how many T elements are there between this pointer and other.
- #<=>(other : self)
Returns -1, 0 or 1 if this pointer's address is less, equal or greater than other's address, respectively.
- #[](offset)
Gets the value pointed at this pointer's address plus
offset * sizeof(T)
. - #[]=(offset, value : T)
Sets the value pointed at this pointer's address plus
offset * sizeof(T)
. - #address : UInt64
Returns the address of this pointer.
- #appender
Returns a
Pointer::Appender
for this pointer. - #clear(count = 1)
Clears (sets to "zero" bytes) a number of values pointed by this pointer.
- #clone
- #copy_from(source : Pointer(T), count : Int)
Copies count elements from source into
self
. - #copy_to(target : Pointer, count : Int)
Copies count elements from
self
into target. - #hash
Returns the address of this pointer.
- #map!(count : Int, &block)
Sets count consecutive values pointed by this pointer to the values returned by the block.
- #memcmp(other : Pointer(T), count : Int)
Compares count elements from this pointer and other, byte by byte.
- #move_from(source : Pointer(T), count : Int)
Copies count elements from source into
self
. - #move_to(target : Pointer, count : Int)
Copies count elements from
self
into source. - #null?
Returns
true
if this pointer's address is zero. - #realloc(size : Int)
Tries to change the size of the allocation pointed to by this pointer to size, and returns that pointer.
- #realloc(size : UInt64) : self
Tries to change the size of the allocation pointed to by this pointer to size, and returns that pointer.
- #shuffle!(count : Int, random = Random::DEFAULT)
Shuffles count consecutive values pointed by this pointer.
- #swap(i, j)
Swaps the contents pointed at the offsets i and j.
- #to_s(io : IO)
Appends a string representation of this pointer to the given
IO
, including its type and address in hexadecimal- - #to_slice(size)
Returns a
Slice
that points to this pointer and is bounded by the given size. - #value : T
Gets the value pointed by this pointer.
- #value=(value : T)
Sets the value pointed by this pointer.
Instance methods inherited from module Comparable(self)
<, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) >, >=(other : T) >= Instance methods inherited from struct Value
==(other) ==, dup dup Instance methods inherited from class Object
!=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)===(other : YAML::Any)
===(other) ===, =~(other) =~, class class, dup dup, hash hash, inspect(io : IO)
inspect inspect, itself itself, not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, tap(&block) tap, to_json(io : IO)
to_json to_json, to_pretty_json(indent : String = " ")
to_pretty_json(io : IO, indent : String = " ") to_pretty_json, to_s
to_s(io : IO) to_s, to_yaml(io : IO)
to_yaml to_yaml, try(&block) try
Class methods inherited from class Object
from_json(string_or_io, root : String) : selffrom_json(string_or_io) : self from_json, from_yaml(string_or_io) : self from_yaml
Class Method Detail
def self.malloc(size : Int, value : T)Source
Allocates size * sizeof(T)
bytes from the system's heap initialized to value and returns a pointer to the first byte from that memory. The memory is allocated by the GC
, so when there are no pointers to this memory, it will be automatically freed-
# An Int32 occupies 4 bytes, so here we are requesting 8 bytes # initialized to the number 42 ptr = Pointer.malloc(2, 42) ptr[0] # => 42 ptr[1] # => 42
def self.malloc(size : UInt64)Source
Allocates size * sizeof(T)
bytes from the system's heap initialized to zero and returns a pointer to the first byte from that memory. The memory is allocated by the GC
, so when there are no pointers to this memory, it will be automatically freed-
# Allocate memory for an Int32: 4 bytes ptr = Pointer(Int32).malloc(1_u64) ptr.value # => 0 # Allocate memory for 10 Int32: 40 bytes ptr = Pointer(Int32).malloc(10_u64) ptr[0] # => 0 # ... ptr[9] # => 0
def self.malloc(size : Int = 1)Source
Allocates size * sizeof(T)
bytes from the system's heap initialized to zero and returns a pointer to the first byte from that memory. The memory is allocated by the GC
, so when there are no pointers to this memory, it will be automatically freed-
# Allocate memory for an Int32: 4 bytes ptr = Pointer(Int32).malloc ptr.value # => 0 # Allocate memory for 10 Int32: 40 bytes ptr = Pointer(Int32).malloc(10) ptr[0] # => 0 # ... ptr[9] # => 0
def self.malloc(size : Int, &block : Int32 -> T)Source
Allocates size * sizeof(T)
bytes from the system's heap initialized to the value returned by the block (which is invoked once with each index in the range 0...size
) and returns a pointer to the first byte from that memory. The memory is allocated by the GC
, so when there are no pointers to this memory, it will be automatically freed-
# An Int32 occupies 4 bytes, so here we are requesting 16 bytes. # i is an index in the range 0 .. 3 ptr = Pointer.malloc(4) { |i| i + 10 } ptr[0] # => 10 ptr[1] # => 11 ptr[2] # => 12 ptr[3] # => 13
def self.new(address : UInt64)Source
Returns a pointer that points to the given memory address. This doesn't allocate memory.
ptr = Pointer(Int32).new(5678_u64) ptr.address # => 5678
def self.new(address : Int)Source
Returns a pointer that points to the given memory address. This doesn't allocate memory.
ptr = Pointer(Int32).new(5678) ptr.address # => 5678
def self.newSource
def self.nullSource
Returns a pointer whose memory address is zero. This doesn't allocate memory.
When calling a C function you can also pass nil
instead of constructing a null pointer with this method.
ptr = Pointer(Int32).null ptr.address # => 0
Instance Method Detail
def +(offset : Int64) : selfSource
Returns a new pointer whose address is this pointer's address incremented by other * sizeof(T)
.
ptr = Pointer(Int32).new(1234) ptr.address # => 1234 # An Int32 occupies four bytes ptr2 = ptr + 1_u64 ptr2.address # => 1238
def +(other : Int)Source
Returns a new pointer whose address is this pointer's address incremented by other * sizeof(T)
.
ptr = Pointer(Int32).new(1234) ptr.address # => 1234 # An Int32 occupies four bytes ptr2 = ptr + 1 ptr2.address # => 1238
def -(other : Int)Source
Returns a new pointer whose address is this pointer's address decremented by other * sizeof(T)
.
ptr = Pointer(Int32).new(1234) ptr.address # => 1234 # An Int32 occupies four bytes ptr2 = ptr - 1 ptr2.address # => 1230
def <=>(other : self)Source
Returns -1, 0 or 1 if this pointer's address is less, equal or greater than other's address, respectively.
See also: Object#<=>
.
def [](offset)Source
Gets the value pointed at this pointer's address plus offset * sizeof(T)
.
ptr = Pointer.malloc(4) { |i| i + 10 } ptr[0] # => 10 ptr[1] # => 11 ptr[2] # => 12 ptr[3] # => 13
def []=(offset, value : T)Source
Sets the value pointed at this pointer's address plus offset * sizeof(T)
.
ptr = Pointer(Int32).malloc(4) # [0, 0, 0, 0] ptr[1] = 42 ptr2 = ptr + 1 ptr2.value # => 42
def address : UInt64Source
Returns the address of this pointer.
ptr = Pointer(Int32).new(1234) ptr.address # => 1234
def appenderSource
Returns a Pointer::Appender
for this pointer.
def clear(count = 1)Source
Clears (sets to "zero" bytes) a number of values pointed by this pointer.
ptr = Pointer.malloc(6) { |i| i + 10 } # [10, 11, 12, 13, 14, 15] ptr.clear(3) ptr.to_slice(6) # => Slice[0, 0, 0, 13, 14, 15]
def cloneSource
def copy_from(source : Pointer(T), count : Int)Source
Copies count elements from source into self
. If source and self
overlap, behaviour is undefined. Use #move_from
if they overlap (slower but always works).
ptr1 = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr2 = Pointer.malloc(4) { |i| i + 11 } # [11, 12, 13, 14] # ptr2 -> [11, 12, 13, 14] # ^---^ <- copy this # ptr1 -> [1, 2, 3, 4] # ^---^ <- here ptr1.copy_from(ptr2, 2) ptr1[0] # => 11 ptr1[1] # => 12 ptr1[2] # => 3 ptr1[3] # => 4
def copy_to(target : Pointer, count : Int)Source
Copies count elements from self
into target. If self
and target overlap, behaviour is undefined. Use #move_to
if they overlap (slower but always works).
ptr1 = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr2 = Pointer.malloc(4) { |i| i + 11 } # [11, 12, 13, 14] # ptr1 -> [1, 2, 3, 4] # ^---^ <- copy this # ptr2 -> [11, 12, 13, 14] # ^---^ <- here ptr1.copy_to(ptr2, 2) ptr2[0] # => 1 ptr2[1] # => 2 ptr2[2] # => 13 ptr2[3] # => 14
def hashSource
Returns the address of this pointer.
ptr = Pointer(Int32).new(1234) ptr.hash # => 1234
def map!(count : Int, &block)Source
Sets count consecutive values pointed by this pointer to the values returned by the block.
ptr = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr.map!(4) { |value| value * 2 } ptr # [2, 4, 6, 8]
def memcmp(other : Pointer(T), count : Int)Source
Compares count elements from this pointer and other, byte by byte.
Returns 0 if both pointers point to the same sequence of count bytes. Otherwise returns the difference between the first two differing bytes (treated as UInt8).
ptr1 = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr2 = Pointer.malloc(4) { |i| i + 11 } # [11, 12, 13, 14] ptr1.memcmp(ptr2, 4) # => -10 ptr2.memcmp(ptr1, 4) # => 10 ptr1.memcmp(ptr1, 4) # => 0
def move_from(source : Pointer(T), count : Int)Source
Copies count elements from source into self
. source and self
may overlap; the copy is always done in a non-destructive manner.
ptr1 = Pointer.malloc(4) { |i| i + 1 } # ptr1 -> [1, 2, 3, 4] ptr2 = ptr1 + 1 # ^--------- ptr2 # [1, 2, 3, 4] # ^-----^ <- copy this # ^------^ <- here ptr2.move_from(ptr1, 3) ptr1[0] # => 1 ptr1[1] # => 1 ptr1[2] # => 2 ptr1[3] # => 3
def move_to(target : Pointer, count : Int)Source
Copies count elements from self
into source. source and self
may overlap; the copy is always done in a non-destructive manner.
ptr1 = Pointer.malloc(4) { |i| i + 1 } # ptr1 -> [1, 2, 3, 4] ptr2 = ptr1 + 1 # ^--------- ptr2 # [1, 2, 3, 4] # ^-----^ <- copy this # ^------^ <- here ptr1.move_to(ptr2, 3) ptr1[0] # => 1 ptr1[1] # => 1 ptr1[2] # => 2 ptr1[3] # => 3
def null?Source
Returns true
if this pointer's address is zero.
a = 1 pointerof(a).null? # => false b = Pointer(Int32).new(0) b.null? # => true
def realloc(size : Int)Source
Tries to change the size of the allocation pointed to by this pointer to size, and returns that pointer.
Since the space after the end of the block may be in use, realloc may find it necessary to copy the block to a new address where more free space is available. The value of realloc is the new address of the block. If the block needs to be moved, realloc copies the old contents.
Remember to always assign the value of realloc.
ptr = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr = ptr.realloc(8) ptr # [1, 2, 3, 4, 0, 0, 0, 0]
def realloc(size : UInt64) : selfSource
Tries to change the size of the allocation pointed to by this pointer to size, and returns that pointer.
Since the space after the end of the block may be in use, realloc may find it necessary to copy the block to a new address where more free space is available. The value of realloc is the new address of the block. If the block needs to be moved, realloc copies the old contents.
Remember to always assign the value of realloc.
ptr = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr = ptr.realloc(8_u8) ptr # [1, 2, 3, 4, 0, 0, 0, 0]
def shuffle!(count : Int, random = Random::DEFAULT)Source
Shuffles count consecutive values pointed by this pointer.
ptr = Pointer.malloc(4) { |i| i + 1 } # [1, 2, 3, 4] ptr.shuffle!(4) ptr # [3, 4, 1, 2]
def swap(i, j)Source
Swaps the contents pointed at the offsets i and j.
ptr = Pointer.malloc(4) { |i| i + 1 } ptr[2] # => 3 ptr[3] # => 4 ptr.swap(2, 3) ptr[2] # => 4 ptr[3] # => 3
def to_s(io : IO)Source
Appends a string representation of this pointer to the given IO
, including its type and address in hexadecimal-
ptr1 = Pointer(Int32).new(1234) ptr1.to_s # => "Pointer(Int32)@0x4d2" ptr2 = Pointer(Int32).new(0) ptr2.to_s # => "Pointer(Int32).null"
def to_slice(size)Source
Returns a Slice
that points to this pointer and is bounded by the given size.
ptr = Pointer.malloc(6) { |i| i + 10 } # [10, 11, 12, 13, 14, 15] slice = ptr.to_slice(4) # => Slice[10, 11, 12, 13] slice.class # => Slice(Int32)
def value : TSource
Gets the value pointed by this pointer.
ptr = Pointer(Int32).malloc(4) ptr.value = 42 ptr.value # => 42
def value=(value : T)Source
Sets the value pointed by this pointer.
ptr = Pointer(Int32).malloc(4) ptr.value = 42 ptr.value # => 42
© 2012–2017 Manas Technology Solutions.
Licensed under the Apache License, Version 2.0.
https://crystal-lang.org/api/0.22.0/Pointer.html