元素类型的背景知识
如果你给MAKE-ARRAY
一个元素类型,你就要求Common Lisp实现创建一个优化了空间布局的数组(!),这个数组可能限制于某些元素类型。你不需要得到正好这种元素类型的数组,而是在这个实现中针对这种元素类型最节省空间的数组。
是否还有其他取决于您使用的实现。
对于任何没有特殊实现的元素类型,元素类型会升级为T
。这意味着数组可以具有各种对象作为元素,并且像数组、字符串、结构体、CLOS对象等较大的元素始终存储为指向堆上对象的指针。
一些特定实现的示例:
整数
CL-USER> (upgraded-array-element-type '(integer 0 1))
(UNSIGNED-BYTE 1)
CL-USER> (upgraded-array-element-type '(integer 0 2))
(UNSIGNED-BYTE 2)
CL-USER> (upgraded-array-element-type '(integer 0 3))
(UNSIGNED-BYTE 2)
CL-USER> (upgraded-array-element-type '(integer 0 4))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 5))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 7))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 8))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 15))
(UNSIGNED-BYTE 4)
CL-USER> (upgraded-array-element-type '(integer 0 16))
(UNSIGNED-BYTE 8)
CL-USER> (upgraded-array-element-type '(integer 0 256))
(UNSIGNED-BYTE 16)
CL-USER> (upgraded-array-element-type '(integer 0 4423423))
(UNSIGNED-BYTE 32)
CL-USER> (upgraded-array-element-type '(integer 0 4423423423423))
(UNSIGNED-BYTE 64)
CL-USER> (upgraded-array-element-type '(integer 0 4423423423423423423423423423423))
T
字符
CL-USER> (upgraded-array-element-type 'character)
CHARACTER
浮动
CL-USER> (upgraded-array-element-type 'single-float)
SINGLE-FLOAT
CL-USER> (upgraded-array-element-type 'long-float)
DOUBLE-FLOAT
数组
CL-USER> (upgraded-array-element-type 'array)
T
即使您请求更具体的数组版本作为元素,您很可能会得到
T
作为答案。
何时请求特殊数组很重要的一个原因是为了节省空间。如果只有位,一般数组可以存储位,但位向量将节省大量空间。
但是: 具有特殊元素类型的数组的操作可能会变慢。在运行时,在安全代码中可能会进行额外的类型检查,并且更改/读取元素的操作可能需要较慢的处理器指令。
因此,Common Lisp没有针对结构数组,向量,CLOS对象等的优化存储布局。由于存储了每个元素的指针,因此访问始终需要间接引用,并且没有任何东西可以保证这些对象按线性顺序存储在内存中。它们在数组中存储的是指向它们的指针。
检查您的实现是否针对浮点数(single, double, long, ...)数组具有优化的空间布局。
Common Lisp支持真正的多维数组,最多具有
ARRAY-RANK-LIMIT
(ABCL在我的ARM上最多具有8个维度,其他某些实现支持更多维度)。这些多维数组也可以具有专门的元素类型。
upgraded-array-element-type
。 - user5920214