clinux-kernellinked-listc99standards-compliance

Kernel's "container_of" - any way to make it ISO conforming?


While looking at Linux kernel's implementation of doubly linked circular lists, I've found following macro:

#define container_of(ptr, type, member) ({           \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})

The way this works is that it returns pointer to structure given only address of one of its members:

struct blabla
{
    int value;
    struct list_head *list;
}

Thus you can get pointer to blabla (and get to "value") given only pointer to list. To my question, how would I make this as portable as possible (best case conforming to C89/C99?). Due to usage of typeof(), this is gcc only.

This is what I've got so far:

#define container_of(ptr, type, member) (                  \
                (type *) (char *)(ptr)-offsetof(type,member)\
                )

Is this snippet conforming to ISO standards (and thus should be able to be compiled on any conforming compiler)?


Solution

  • As Ouah commented, the ({ ... }) statement expression is a GNU extension; you won't be able to use that. Your core expression is close to what's required, but doesn't have enough parentheses:

    #define container_of(ptr, type, member) \
                          ((type *) ((char *)(ptr) - offsetof(type, member)))
    

    That looks clean to me. It's only spread across two lines for SO.