On Sun, 06 Jul 2008 20:08:35 -0700, Peter Nilsson wrote:
> John Koleszar wrote:
>> ...Consider this stripped down example:
>>
>> #include <stddef.h>
>> struct s { int a[3]; int b; };
>> void foo(void) {
>> switch(0) {case offsetof(struct s,a[0]):;}
>> }
>>
>> The relevant part of the C standard says that:
>> 7.17 Common definitions <stddef.h>
>> <snip>
>> 3 The macros are
>> <snip>
>> offsetof(type, member-designator)
>> which expands to an integer constant expression that has type size_t,
>> the value of which is the offset in bytes, to the structure member
>> (designated by member-designator), ...
>
> Note that you have not supplied a structure member. What you need is:
> offsetof(struct s, a)
>
I agree, for the simple definition of structure member. I did consider
this clause. I suppose I focused more on the address constant portion of
the definition because I couldn't think of an example where, given that
member-designator is a simple Member, the controlling expression &
(t.member-designator) does not evaluate to an address constant. I assume
that the spec is not being redundant, so I read the term "member" a
little looser here. Maybe I'm missing something obvious. Can you show me
a case that meets the first clause (simple member) but not the second
(address constant)?
>> from the beginning of its structure (designated by type). The type
>> and member designator shall be such that given
>> static type t;
>> then the expression &(t.member-designator) evaluates to an address
>> constant. (If the specified member is a bit- field, the behavior is
>> undefined.)
>>
>> It's my feeling that &(t.a[0]) does (can, should) evaluate to an
>> address constant, as the types are all complete.
>
> Feel away. Just realise that your feelings are incidental. 
>
Sorry, bad choice of words. s/feeling/interpretation/. I'm quite aware
that it doesn't make a lick of difference what I think
>> Other compilers (at least two different vendors) are able to evaluate
>> this expression as an address constant. However, the new compiler
>> raises an error 'case expression not constant.' The new compiler is
>> able to properly evaluate the offsetof a or b, but not any element of
>> a.
>
> AFAICS, no implementation is required to.
>
Do you mean within the context of offsetof? I still think that &(t.a[0])
is required by the standard to be a valid address constant. From 6.6.9:
An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary &
operator or an integer constant cast to pointer type, or implicitly by
the use of an expression of array or function type. The array-subscript
[] and member-access . and -> operators, the address & and indirection
* unary operators, and pointer casts may be used in the creation of an
address constant, but the value of an object shall not be accessed by
use of these operators.
FWIW, the new compiler does accept the member-access operator in the
member-designator operand, just not the array-subscript. Not relevant if
member-designator is required to be a simple member, of course.
>> What I'd really like is offsetof c.bar[0].baz, but it seems to choke on
>> any subscripted element.
>
> offsetof(c, bar) + offsetof(<bar's type>, baz)
Of course, I know the workarounds (or the Right Way, depending on your
perspective). Just hoping to keep the syntax more compact, as expanding
it obscures the intent, thus requiring a comment and making it even more
verbose, not to mention slightly less safe (could silently fail if
typeof<s.c> != struct c):
ct_assert(offsetof(struct s, c.bar[0].baz)%4==0)
vs
ct_assert((offsetof(struct s, c)
+ offsetof(struct c, bar)
+ offsetof(struct b, baz))%4==0)
Gets worse with real names, of course. It's irrelevant as I have to work
around the issue anyway, just wanted to give a bigger picture as to what/
why I'm trying to achieve.
John