Hello! While using (system foreign) in a couple of projects I found myself doing quite a bit of pointer arithmetic in Scheme: --8<---------------cut here---------------start------------->8--- (define (foreign-array->list array-pointer element-count) (let ((array (pointer->bytevector array-pointer (* element-count (sizeof '*))))) (unfold (cut >= <> element-count) (lambda (element) (let ((start (* element (sizeof '*)))) (bytevector->pointer array start))) 1+ 0))) (define (pointer+ array-pointer type index) (let ((offset (* index (align (sizeof type) (alignof type))))) (make-pointer (+ (pointer-address array-pointer) offset)))) (define (foreign-string-array->list array len) ;; Return a list of string comprising the LEN strings pointed to by the ;; elements of ARRAY, a pointer to an array of pointers. (unfold (cut < <> 0) (lambda (index) (let ((ptr (make-pointer (+ (pointer-address array) (* index (sizeof '*)))))) (pointer->string (dereference-pointer ptr)))) 1- (- len 1))) --8<---------------cut here---------------end--------------->8--- (Examples from .) The problem is that each ‘make-pointer’ call (and ‘dereference-pointer’, etc.) conses. This can make conversion to/from C quite inefficient. In addition, 90% of the C pointers of interest are 8-byte aligned---that’s on x86_64-linux-gnu, but it surely holds on most platforms, at least for pointers returned by ‘malloc’. So, here comes the idea of “immediate pointers”, which would fit in a word. A 3-bit tag is used, as for immediate numbers & co; pointers that aren’t 8-byte aligned are still stored in an scm_tc7_pointer cell. I experimented with it using ‘scm_tc3_unused’ (== 3). Alas, that can’t work, because it makes it impossible to use such an object as the ‘car’ of a pair: #define SCM_I_CONSP(x) (!SCM_IMP (x) && ((1 & SCM_CELL_TYPE (x)) == 0)) I would welcome feedback and help from tag-savvy people. Thanks, Ludo’.