Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > address of static array element as address constant

Reply
Thread Tools

address of static array element as address constant

 
 
John Koleszar
Guest
Posts: n/a
 
      07-07-2008
Hi all,

I'm porting some code that provides compile-time assertions from one
compiler to another and ran across what I believe to be compliant code
that won't compile using the new compiler. Not naming names here to
remove bias - I'm trying to tell if I'm relying on implementation defined
behavior or if this is a bug in the new compiler.

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), 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. 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. What I'd really like is offsetof c.bar
[0].baz, but it seems to choke on any subscripted element. a[0] does work
as part of a non-constant expression though, eg printf(offsetof(a[0]))

So, what say the language lawyers?

br,

John
 
Reply With Quote
 
 
 
 
Peter Nilsson
Guest
Posts: n/a
 
      07-07-2008
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)

> 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.

> 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.

> 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)

--
Peter
 
Reply With Quote
 
 
 
 
Peter Nilsson
Guest
Posts: n/a
 
      07-07-2008
Peter Nilsson wrote:
> John Koleszar wrote:
> > 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)


Er...

offsetof(<c's type>, bar) + offsetof(<bar's type>, baz)

--
Peter
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      07-07-2008
On 2008-07-07, John Koleszar <(E-Mail Removed)> 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]):;}
> }


Have you tried offsetof(struct s, a)?

> 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)


But a[0] is not a member designator. It is the 'a' which is the 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), 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


Given t.a[0], the syntax is actually (t.a)[0]. The postfix operator []
has nothing to do with the structure member access; it's operating
on a pointer which comes out of the t.a expression.

> constant. However, the new compiler raises an error 'case expression not
> constant.'


Indeed, because the expression contains evaluated pointer dereferencing.

The other compiler must be accepting this as an extension.
 
Reply With Quote
 
John Koleszar
Guest
Posts: n/a
 
      07-07-2008
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
 
Reply With Quote
 
John Koleszar
Guest
Posts: n/a
 
      07-15-2008

On Mon, 2008-07-07 at 12:11 +0000, John Koleszar wrote:
> 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.


ping... can anyone else weigh in on this, or point me to a more formal
definition of member? I didn't see it called out on the glossary with
the other formal terms. This issue is is still ambiguous in my mind.

Thanks!

-- John


 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      07-15-2008
John Koleszar <(E-Mail Removed)> writes:

> On Mon, 2008-07-07 at 12:11 +0000, John Koleszar wrote:

<snip>
>> 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.

>
> ping... can anyone else weigh in on this, or point me to a more formal
> definition of member? I didn't see it called out on the glossary with
> the other formal terms. This issue is is still ambiguous in my mind.


The advice seems sound and includes a quote from the standard. What
you seem to want (offsetof(struct s, c.bar[0].baz)) is clearly not
permitted (though it might be provided as an extension, of course) and
you have identified the correct way to do it (your second ct_assert
example). Messy, but I can't see how you can avoid it.

--
Ben.
 
Reply With Quote
 
John Koleszar
Guest
Posts: n/a
 
      07-15-2008

On Tue, 2008-07-15 at 16:07 +0100, Ben Bacarisse wrote:
> John Koleszar <(E-Mail Removed)> writes:
>
> > On Mon, 2008-07-07 at 12:11 +0000, John Koleszar wrote:

> <snip>
> >> 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.

> >
> > ping... can anyone else weigh in on this, or point me to a more formal
> > definition of member? I didn't see it called out on the glossary with
> > the other formal terms. This issue is is still ambiguous in my mind.

>
> The advice seems sound and includes a quote from the standard. What
> you seem to want (offsetof(struct s, c.bar[0].baz)) is clearly not
> permitted (though it might be provided as an extension, of course) and
> you have identified the correct way to do it (your second ct_assert
> example). Messy, but I can't see how you can avoid it.
>


All of the quotes of the standard in this thread are mine, I'm just
having a bit of trouble parsing them.

My question wrt section 7.17.3 is whether the spec is being redundant or
whether there are two independant clauses in effect. That is, is there a
case where for a simple member the expression &(t.member) does not
evaluate to an address constant?

Aha, now I see it. I've been glossing over the parenthetical '(If the
specified member is a bit- field, the behavior is undefined)' which
explains the need for the second clause.

Sorry for the noise. (Now how do I send an enhancement request to
ISO )

br,

John


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Can I include include a constant in a constant array? Fredxx VHDL 3 07-15-2009 07:39 AM
how to Update/insert an xml element's text----> (<element>text</element>) HANM XML 2 01-29-2008 03:31 PM
One-element constant array Amal VHDL 2 10-19-2007 04:30 PM
"error C2057: expected constant expression", "error C2466: cannot allocate an array of constant size 0". Why doesn't my simple program work??? hn.ft.pris@gmail.com C++ 13 01-22-2007 02:03 PM
non static compile time constant .vs. static in tomcat ptg_abhishek@yahoo.com Java 1 11-17-2005 11:35 AM



Advertisments