1

I am reading Linux Device Drivers Development from John Madieu and one para says

The container_of macro won't work for char * or array members. It
means the first member of container_of must not be a pointer to
another pointer to char nor to array in the structure.

This is the definition of container_of :

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

So if I have

struct person {
int age;
int salary;
char *name;
} me;

and I have char ** my_name = &(me.name);, why can't I do the following :

struct person * me = container_of(my_name,struct person,name);
Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
Naveen
  • 7,944
  • 12
  • 78
  • 165

1 Answers1

1

This is due to ISO C rules on pointer initialisations, which break the initialisation of __mptr for this case.

Here's a stripped-back example:

int main()
{
    char ar[5] = {0};
    const char (*ptr)[5] = &ar;
}

// warning: pointers to arrays with different qualifiers are incompatible in ISO C [-Wpedantic]

(live demo)

There is a discussion about this problem on a prior SO question. Note that C++ has no such limitation; the const may be added freely.

A kernel dev discussion suggested replacing __mptr with another way to perform the type check inside container_of, so you may find that this already no longer affects you.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    A [later version of the patch](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c7acec713d14c6ce8a20154f9dfda258d6bcad3b) in that kernel dev discussion eventually made it into kernel version 4.13. (Actually, it ended up as the last part of a [series of 6 patches](https://lore.kernel.org/lkml/xa1t4lw9hw55.fsf@mina86.com/t/) that I wrote.) – Ian Abbott Jan 03 '19 at 15:04