Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)?

like image 355
Tomas Pruzina Avatar asked Apr 22 '12 16:04

Tomas Pruzina


1 Answers

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.

like image 92
Jonathan Leffler Avatar answered Nov 12 '22 23:11

Jonathan Leffler