memref

This function and the related function memref-int calculate an address in memory
and performs a read from that address. This function takes an object
as an argument while memref-int takes an address.

The width and style of the read depends upon the
type. The possible values for the
type argument are shown in a table below.

Except when the type argument
is :lisp, the result is always a number, either an
integer or float. The type and possible range of that number
depends on the type argument.
This function is setf'able. The setf function writes
to the addressed memory instead of reading from it.

The object argument may be any Lisp value.
If the Lisp value represents an object in the heap, the address of the
object (including its tag) is used as the base address in the memory
reference. If the Lisp value is an immediate value (a fixnum, a
character, ...), then the actual bit representation of the Lisp value
(including its tag) is used as the base address in the memory
reference.

The offset and pos arguments
must be fixnum values. The sum of these two arguments is added to the
base address value and the result is treated as an address in memory
from which data is fetched, or to which data is stored.

When the coerce argument is non-nil some checking is done in the setf form. The
value to be stored is coerced to the required type.

This function provides low-level memory access in Allegro
CL. However, even though the name is exported and
documented, we recommend against using this function in user code. Instead, we
recommend using higher-level functions, such as those linked to
below. However, the function is useful in the development cycle for
debugging purposes.

WARNING about setf: except when the type
is :lisp, the setf function does not do any
setf-protection. If it is used to store non-Lisp values into a memory
location that was intended to hold a Lisp value, then a
non-recoverable error is very likely to occur during the next GC.

The access-types (possible values of type)
that are available are as follows:

Programming Notes

The function memref is
very similar to the memref-int function, but because the base
address determination is significantly different the descriptions are
different in several subtle but important ways.

When optimization is declared at a sufficient level, the call to
memref and to the setf
form, is compiled in line and is thus very efficient. Note that when
the optional coerce argument is supplied, then
the call is not open-coded when compiled.

When the coerce argument is non-nil some checking is done in the setf form. The
value to be stored is coerced to the required type. This is
especially useful when the argument is a float value, but of the wrong
type, as in

(setf (sys:memref-int array-address 0 0 :double-float :coerce) 1.0s0)

The offset and pos are
equivalent and interchangeable. They are both added as byte-offsets to
the base address to determine the final memory address. Usually, the
offset is some constant that adjusts for the
start of the data in some object being accessed.

An offset is necessary to access Lisp objects because a Lisp object pointer
contains tag bits in the low-order positions. When the pointer is treated
as a machine address, the numeric value is not the address of the Lisp
data object in memory. The address is normally lower than the address of the
object, by a fixed amount determined by the tag bits in the pointer.

Some of the offsets for Lisp objects are described in
[Allegro directory]/misc/lisp.h in the Allegro CL
distribution. In an earlier version of this documentation, it was
stated that the offsets are available in Lisp itself by calling
certain otherwise undocumented functions. That statement was
incorrect. The offsets are not reliably available with Lisp.

In all 32-bit implementations, a Lisp fixnum is represented by the
numeric value shifted left by 2 bits. Thus, the fixnum 1 is
represented by the machine word #x00000004. When a fixnum is passed
as the object argument to memref, the effective memory address is the
(32-bit) word in memory indexed by the fixnum value. Thus, the fixnum
0 addresses the 0-th word at address 0, the fixnum 1 addresses the
1-th word at address 4, etc. This feature is very useful when
referencing blocks of foreign storage aligned on a word boundary. The
numeric address of the block is divided by 4 to obtain the fixnum word
index of the block. The index is always a fixnum since all memory
addresses must fit within a 32-bit machine word. The foreign type
facility recognizes this interpretation of fixnums as the :aligned
foreign pointer type.

In the 64-bit implementations, a Lisp fixnum is a numeric value shifted
left by 3 bits. Thus a fixnum represents a double-word index and the
above discussion must be modified accordingly.