On Tue, Sep 22, 2009 at 02:56:05AM -0400, Mike Kaplinskiy wrote: > On Tue, Sep 22, 2009 at 1:09 AM, Vitaliy Margolen > <wine-de...@kievinfo.com> wrote: > > Ben Klein wrote: > >> The question remains, how exactly does > >> FIELD_OFFSET work, and does it end up dereferencing ca[5]? > > It does pointer arithmetic and does not dereference anything. "ca[5]" is the > > same as "(ca + 5)" or on lower level "((char*)ca + 5*sizeof(ca[0]))" and > > does not require any dereferencing. > > It does, since field offset macro takes the easy approach: > #define FIELD_OFFSET(type, field) ((LONG)(INT_PTR)&(((type *)0)->field)) > > which basically dereferences a null pointer to get the offset. This > would be a bug in cppcheck since we don't actually dereference ca[5]. > Moreover, since cppcheck doesn't catch the similar FIELD_OFFSET uses > as bugs, it seems that it is mistaking ca[5] for the local ca, as > opposed to the cs_t->ca.
I suspect that the above is technically illegal C. Mainly because pointer arithmetic is only defined for pointers to objects - and no object can have the address 0. This is why offsetof() is defined as a builtin in more recent GCC. The case in question tries to evaluate: ((LONG)(INT_PTR)&(((type *)0)->ca[5])) which does seem to contain a reference to beyond the end of the array! Modern C allows the last entry of a struct to be ca[] (ie no array bound) for these situations where a structure will be malloced with dynamic size. There is, however, a fubar in the standard. offsetof() is defined to return a compile-time constant - so the result can be used as an array size etc. However there are times when you want to do: offsetof(type, array_member[expression]) and this now reported as illegal by gcc unless 'espression' is a compile time constant :-( David -- David Laight: da...@l8s.co.uk