Discussion:
Question about container_of macro.
Manish Katiyar
2008-01-17 18:08:09 UTC
Permalink
Hi,

I am sorry for spamming, it really isn't a usb related question, but I
didn't get the answer on kernelnewbies list. I am sure will get it
from here........atleast from Greg :-) since I am referring his
article.


---------- Forwarded message ----------
From: Manish Katiyar <***@gmail.com>
Date: Jan 16, 2008 11:08 PM
Subject: Question about container_of macro.
To: kernelnewbies <***@nl.linux.org>


Hi,

It might be a very silly question, but I was going through the
definition and explaination of container_of macro from the below link
http://www.kroah.com/log/linux/container_of.html.

However what i understood is that, given a pointer to one of the
members of a structure, it would return a pointer to the parent
structure.

My question is instead of defining container_of as:

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


Why won't this simply work :

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


Since even after declaring __mptr as member type we are anyway
typecasting it to char *. I am sure I must be missing something very
silly :-( ...

Thanks in advance.

--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Alan Stern
2008-01-17 19:39:52 UTC
Permalink
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) - offsetof(type,member) );})
Indeed, or even this:

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

Alan Stern


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Laurent Pinchart
2008-01-18 00:01:54 UTC
Permalink
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) - offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) - offsetof(type,member)))
If I'm not mistaken, that's because

const typeof( ((type *)0)->member ) *__mptr = (ptr);

will warn (or maybe even bail out ?) if ptr is not a pointer to a variable of
member's type.

Laurent Pinchart

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Manish Katiyar
2008-01-18 04:15:27 UTC
Permalink
Hi Laurent,
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) - offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) - offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a variable of
member's type.
But even if ptr is not a variable of member's type, in the second line
we are force typecasting it to char * and then subtracting. I guess it
will not warn. I tried in a simple program and it doesn't shout.
Below is the program

#include <stdio.h>
#include <stddef.h>

struct t_s{
int a;
int b;
};

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

int main()
{
struct t_s init;
char *c;
init.a = 1;
init.b = 2;

c = (char *)&(init.b);

printf("a = %d\n",(container_of(c,struct t_s,b))->a);
return 0;
}

/home/mkatiyar> gcc -Wall b.c
b.c: In function 'main':
b.c:19: warning: assignment from incompatible pointer type
/home/mkatiyar> ./a.out
a = 1


Thanks
Post by Laurent Pinchart
Laurent Pinchart
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Manish Katiyar
2008-01-18 04:29:50 UTC
Permalink
Post by Manish Katiyar
Hi Laurent,
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) - offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) - offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a variable of
member's type.
But even if ptr is not a variable of member's type, in the second line
we are force typecasting it to char * and then subtracting. I guess it
will not warn. I tried in a simple program and it doesn't shout.
Below is the program
#include <stdio.h>
#include <stddef.h>
struct t_s{
int a;
int b;
};
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) -
offsetof(type,member)))
int main()
{
struct t_s init;
char *c;
init.a = 1;
init.b = 2;
c = (char *)&(init.b);
printf("a = %d\n",(container_of(c,struct t_s,b))->a);
return 0;
}
/home/mkatiyar> gcc -Wall b.c
b.c:19: warning: assignment from incompatible pointer type
/home/mkatiyar> ./a.out
a = 1
Sorry, I pasted the wrong command output........the program doesn't
give any warnings....
Post by Manish Katiyar
Thanks
Post by Laurent Pinchart
Laurent Pinchart
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Laurent Pinchart
2008-01-18 09:14:44 UTC
Permalink
Post by Manish Katiyar
Hi Laurent,
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr =
(ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) -
offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) -
offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a
variable of member's type.
But even if ptr is not a variable of member's type, in the second line
we are force typecasting it to char * and then subtracting. I guess it
will not warn. I tried in a simple program and it doesn't shout.
Below is the program
That's why you need

const typeof( ((type *)0)->member ) *__mptr = (ptr);

in addition to

(type *)( (char *)__mptr - offsetof(type,member) );

otherwise you'll get no warning.

Laurent Pinchart

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Manish Katiyar
2008-01-18 09:48:49 UTC
Permalink
Post by Laurent Pinchart
Post by Manish Katiyar
Hi Laurent,
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr =
(ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) -
offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) -
offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a
variable of member's type.
But even if ptr is not a variable of member's type, in the second line
we are force typecasting it to char * and then subtracting. I guess it
will not warn. I tried in a simple program and it doesn't shout.
Below is the program
That's why you need
const typeof( ((type *)0)->member ) *__mptr = (ptr);
in addition to
(type *)( (char *)__mptr - offsetof(type,member) );
otherwise you'll get no warning.
Got it ..!!! .... thanks a lot laurent... have been scratching my head
over this for past 2 days :-) ..
Post by Laurent Pinchart
Laurent Pinchart
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Manish Katiyar
2008-01-18 16:37:46 UTC
Permalink
Post by Laurent Pinchart
Post by Manish Katiyar
Hi Laurent,
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr =
(ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) -
offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) -
offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a
variable of member's type.
But even if ptr is not a variable of member's type, in the second line
we are force typecasting it to char * and then subtracting. I guess it
will not warn. I tried in a simple program and it doesn't shout.
Below is the program
That's why you need
const typeof( ((type *)0)->member ) *__mptr = (ptr);
in addition to
(type *)( (char *)__mptr - offsetof(type,member) );
otherwise you'll get no warning.
But again, keeping in mind that this macro is one of frequently used
macros in kernel code, i am not sure how much it is justified to
allocate a local variable every time and then removing it without any
significant purpose. If we are keeping it just to ensure some rare
warnings, I would say it is an overkill and probably we can get rid of
it.

Comments/ suggetions ??

Thanks
Post by Laurent Pinchart
Laurent Pinchart
--
Thanks & Regards,
********************************************
Manish Katiyar ( http://mkatiyar.googlepages.com )
3rd Floor, Fair Winds Block
EGL Software Park
Off Intermediate Ring Road
Bangalore 560071, India
***********************************************

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
Laurent Pinchart
2008-01-18 22:19:53 UTC
Permalink
Post by Manish Katiyar
Post by Laurent Pinchart
Post by Manish Katiyar
Hi Laurent,
On Jan 18, 2008 5:31 AM, Laurent Pinchart
Post by Laurent Pinchart
Post by Alan Stern
Post by Manish Katiyar
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr =
(ptr); (type *)( (char *)__mptr - offsetof(type,member) );})
#define container_of(ptr, type, member) ({ \
(type *)( (char *)(ptr) -
offsetof(type,member) );})
#define container_of(ptr, type, member) \
((type *) ((char *)(ptr) -
offsetof(type,member)))
If I'm not mistaken, that's because
const typeof( ((type *)0)->member ) *__mptr = (ptr);
will warn (or maybe even bail out ?) if ptr is not a pointer to a
variable of member's type.
But even if ptr is not a variable of member's type, in the second
line we are force typecasting it to char * and then subtracting. I
guess it will not warn. I tried in a simple program and it doesn't
shout. Below is the program
That's why you need
const typeof( ((type *)0)->member ) *__mptr = (ptr);
in addition to
(type *)( (char *)__mptr - offsetof(type,member) );
otherwise you'll get no warning.
But again, keeping in mind that this macro is one of frequently used
macros in kernel code, i am not sure how much it is justified to
allocate a local variable every time and then removing it without any
significant purpose. If we are keeping it just to ensure some rare
warnings, I would say it is an overkill and probably we can get rid of
it.
The gcc optimiser does a great job and doesn't generate any code for the
type-checking statement.

Regards,

Laurent Pinchart

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
linux-usb-***@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Loading...