On 10/14/2016 11:39 AM, Paolo Bonzini wrote: > >>> Another possibility is a macro like >>> >>> #define field_at_offset(base, offset, type) \ >>> ((type) (((char *) (base)) + (offset))) >>> >>> so that you can do >>> >>> *field_at_offset(void **, elm, (entry) + QTAILQ_NEXT_OFFSET) = NULL; >>> *field_at_offset(void ***, elm, (entry) + QTAILQ_PREV_OFFSET) = >>> *field_at_offset(void ***, head, QTAILQ_LAST_OFFSET); >>> **field_at_offset(void ***, head, QTAILQ_LAST_OFFSET) = (elm); >>> *field_at_offset(void ***, head, QTAILQ_LAST_OFFSET) = >>> field_at_offset(void **, elm, (entry) + QTAILQ_NEXT_OFFSET); >> >> The thing is that we don't know type at all. So only the offset values >> is used. This is intended for QTAILQ of any type. > > Sure, my code is identical to yours---just with more macros for readability, > and a little more type-safe. Another possibility: > > #define QTAILQ_RAW_NEXT(elm, entry) \ > (*field_at_offset(void **, elm, (entry) + QTAILQ_NEXT_OFFSET)) > #define QTAILQ_RAW_PREV(elm, entry) \ > (*field_at_offset(void ***, elm, (entry) + QTAILQ_PREV_OFFSET)) > #define QTAILQ_RAW_LAST(head) \ > (*field_at_offset(void ***, head, QTAILQ_LAST_OFFSET)) > > QTAILQ_RAW_NEXT(elm, entry) = NULL; > QTAILQ_RAW_PREV(elm, entry) = QTAILQ_RAW_LAST(head); > *QTAILQ_RAW_LAST(head) = (elm); > QTAILQ_RAW_LAST(head) = &QTAILQ_RAW_NEXT(elm, entry); >
You are right. The readability can be approved. Thanks, Jianjun > Thanks, > > Paolo > >> Thanks, >> Jianjun >> >>> >>> or something like that (note that I've always used the same type for >>> next and last, by the way). >>> >>> Paolo >>> >> >> >