Hello all,

The file include/common/mini-clist.h contains useful macros to deal with linked 
lists.

One line that we stumbled on is the definition of macro LIST_ELEM(), which 
computes
the address of a node from the address of one of its members:

http://git.haproxy.org/?p=haproxy.git;a=blob;f=include/common/mini-clist.h;h=3c3f0018f31fdaa225cb685159c1cb732ca62e11;hb=HEAD#l130

#define LIST_ELEM(lh, pt, el) ((pt)(((void *)(lh)) - ((void *)&((pt)NULL)->el)))

The construct &((pt)NULL)->el would be advantageously replaced with offsetof:
http://en.wikipedia.org/wiki/Offsetof

Some compilers' implementation of offsetof may expand to exactly 
&((pt)NULL)->el, but this
does not mean that it is a good idea to use this form in a C program.
Apart from readability, compilers are more and more agressive with respect to 
taking advantage
of undefined constructs. GCC's definition now expands to __builtin_offsetof
in readiness for a future optimization that will declare the code as 
unreachable since
it treats NULL as the address of an object, which is undefined behavior (yes,
even though no dereferencing happens).

But this message is not to encourage usage of offsetof, but to discourage the 
use
of pointer arithmetic with void * pointers. Considering that void is an 
incomplete type
and does not have a size, doing arithmetic with it does not seem like a good 
idea.
GCC treats void * pointer arithmetic as if it was char * pointer arithmetic, 
but this is
a non-standard extension that compilers that do not aim for GCC compatibility do
not have to implement :

$ cat t.c
int main() {
  char t[10];
  return (void*)(t+1) - (void*)t;
}
$ gcc t.c
$ gcc -pedantic t.c
t.c:3:23: warning: arithmetic on pointers to void is a GNU extension 
[-Wpointer-arith]
  return (void*)(t+1) - (void*)t;
         ~~~~~~~~~~~~ ^ ~~~~~~~~
1 warning generated.

It is not necessarily convenient to switch to offsetof, since as standardized, 
that macro takes the destination
type, whereas LIST_ELEM takes a pointer to that type. But only getting rid of 
the -Wpointer-arith warning
may be as small a change as:

#define LIST_ELEM(lh, pt, el) ((pt)(((char *)(lh)) - ((size_t)&((pt)NULL)->el)))

Reply via email to