On 2012-06-21 23:47, David Laight wrote:
On Thu, Jun 21, 2012 at 12:56:43PM +0200, Thomas Faber wrote:
On 2012-06-21 12:34, Dmitry Timoshkov wrote:
Thomas Faber thfabba@gmx.de wrote:
FIELD_OFFSET isn't constant "enough".
The problem is not with FIELD_OFFSET, but with applying shift and mask operations to a constant.
You're right, it's actually a combination of multiple factors. I'm not sure what exactly its problem is - the gist is, FIELD_OFFSET cannot reliably be assumed constant.
E.g. the following code only complains about c4:
struct a { char a; int b[5]; int c; }; int c1 = (int)&(((struct a *)0)->a) << 8; int c2 = (int)&(((struct a *)0)->b[0]); int c3 = (int)&(((struct a *)0)->b[0]) + 1; int c4 = (int)&(((struct a *)0)->b[0]) << 8;
This is a bug in the microsoft C compiler. It won't let you do multiply or divide offsetof(struct, array_member[index]) by anything and still get a compile-time constant. The C language requires offsetof() be a compile-time constant, so this ought to be allowed. I couldn't find anything that looked like 'offsetof' that would generate a real compile-time constant.
I can't remember whether it is 'constant enough' to let you do: static char fubar[offsetof(struct a, b[3])];
Yeah, after some reading it seems clear that it's only with array[index] as a member designator.
From reading, it also seems that offsetof should indeed be constant enough
for all of these purposes - but I won't consider myself qualified to nitpick on the contents of the standard in this regard.
In conclusion, assuming working around MSVC bugs like this is worth the effort (which I do think it is), FIELD_OFFSET(struct, array) + index * sizeof(type) can be used as a compatible replacement.
Seems a workable alternative to me. I've submitted a new patch accordingly.
-Tom