Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #149945 > unrolled thread
| Started by | David Brown <david.brown@hesbynett.no> |
|---|---|
| First post | 2020-02-11 15:31 +0100 |
| Last post | 2020-02-16 16:03 -0800 |
| Articles | 20 on this page of 40 — 11 participants |
Back to article view | Back to comp.lang.c
Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-11 15:31 +0100
Re: Offsetof with array elements Guillaume <message@bottle.org> - 2020-02-11 16:08 +0100
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-11 08:32 -0800
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-11 18:46 +0100
Re: Offsetof with array elements Manfred <noname@add.invalid> - 2020-02-11 19:24 +0100
Re: Offsetof with array elements Manfred <noname@add.invalid> - 2020-02-11 19:36 +0100
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-11 22:50 -0500
Re: Offsetof with array elements Manfred <noname@add.invalid> - 2020-02-12 13:53 +0100
Re: Offsetof with array elements Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-18 01:43 -0800
Re: Offsetof with array elements Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-18 01:39 -0800
Re: Offsetof with array elements Bart <bc@freeuk.com> - 2020-02-11 16:56 +0000
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-11 18:49 +0100
Re: Offsetof with array elements Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-11 21:00 +0100
Re: Offsetof with array elements Bart <bc@freeuk.com> - 2020-02-11 20:13 +0000
Re: Offsetof with array elements Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-11 21:24 +0100
Re: Offsetof with array elements Bart <bc@freeuk.com> - 2020-02-11 20:33 +0000
Re: Offsetof with array elements Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-11 21:39 +0100
Re: Offsetof with array elements Bart <bc@freeuk.com> - 2020-02-11 20:48 +0000
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-12 10:56 +0100
Re: Offsetof with array elements Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-12 14:07 +0100
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-12 15:24 +0100
Re: Offsetof with array elements Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-02-12 10:39 +0000
Re: Offsetof with array elements Bonita Montero <Bonita.Montero@gmail.com> - 2020-02-12 14:08 +0100
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-12 05:29 -0800
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-12 11:45 -0800
Re: Offsetof with array elements Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-02-12 17:50 +0000
Re: Offsetof with array elements Tim Rentsch <tr.17687@z991.linuxsc.com> - 2020-02-16 02:41 -0800
Re: Offsetof with array elements Ben Bacarisse <ben.usenet@bsb.me.uk> - 2020-02-16 11:18 +0000
Re: Offsetof with array elements already5chosen@yahoo.com - 2020-02-13 02:42 -0800
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-14 00:20 -0500
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-14 08:24 +0100
Re: Offsetof with array elements already5chosen@yahoo.com - 2020-02-14 03:59 -0800
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-14 15:25 +0100
Re: Offsetof with array elements already5chosen@yahoo.com - 2020-02-16 03:15 -0800
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-16 14:09 +0100
Re: Offsetof with array elements already5chosen@yahoo.com - 2020-02-16 06:36 -0800
Re: Offsetof with array elements James Kuyper <jameskuyper@alumni.caltech.edu> - 2020-02-15 08:18 -0500
Re: Offsetof with array elements David Brown <david.brown@hesbynett.no> - 2020-02-15 15:49 +0100
Re: Offsetof with array elements fir <profesor.fir@gmail.com> - 2020-02-12 04:40 -0800
Re: Offsetof with array elements "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2020-02-16 16:03 -0800
Page 1 of 2 [1] 2 Next page →
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-02-11 15:31 +0100 |
| Subject | Offsetof with array elements |
| Message-ID | <r1udrq$hoe$1@dont-email.me> |
#include <stddef.h>
struct S {
int a[10];
};
int test(int i) {
return offsetof(struct S, a[i]);
}
Is this allowed in standard C? It works in most compilers I tried (even
in the most pedantic modes I checked on gcc), but failed in one embedded
compiler. According to the standard, "offsetof" expands to "an integer
constant expression", and "&s.a[i]" must evaluate to an address constant
(where "s" is an object of type "struct S").
So by my reading, the standard C does not require the expression in
"test" to be valid, and allows a conforming compiler to reject it.
Equally, it does not require a diagnostic, and allows a conforming
compiler to accept it without complaint.
[toc] | [next] | [standalone]
| From | Guillaume <message@bottle.org> |
|---|---|
| Date | 2020-02-11 16:08 +0100 |
| Message-ID | <r1ug0k$fvk$1@gioia.aioe.org> |
| In reply to | #149945 |
Le 11/02/2020 à 15:31, David Brown a écrit :
> #include <stddef.h>
>
> struct S {
> int a[10];
> };
>
> int test(int i) {
> return offsetof(struct S, a[i]);
> }
>
>
> Is this allowed in standard C? It works in most compilers I tried (even
> in the most pedantic modes I checked on gcc), but failed in one embedded
> compiler. According to the standard, "offsetof" expands to "an integer
> constant expression", and "&s.a[i]" must evaluate to an address constant
> (where "s" is an object of type "struct S").
>
> So by my reading, the standard C does not require the expression in
> "test" to be valid, and allows a conforming compiler to reject it.
> Equally, it does not require a diagnostic, and allows a conforming
> compiler to accept it without complaint.
From what I read: "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.)"
In your example, &(t.a[i]) would evaluate to an address constant indeed,
and obviously a[i] doesn't fall into the undefined behavior category as
it's not a bit field.
There's just a small "but": the standard defines offsetof() with its
second parameter being a struct member designator. a[i] is not, unless
I'm mistaken, a member designator, but an expression derived from one.
Thus you'd be using offsetof() with (IMO) an invalid parameter, and this
should be reasonably rejected by a conforming compiler. It looks like
some compilers choose to make this implementation-defined instead. Just
my opinion on this.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2020-02-11 08:32 -0800 |
| Message-ID | <0150dd64-4217-49bc-88d0-e8f8925a9dd2@googlegroups.com> |
| In reply to | #149946 |
"The array-subscript [ ] operator ... may be used in the creation of an address constant, but the value of an object may not be accessed by the use of [that] operator." (6,6p9).
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-02-11 18:46 +0100 |
| Message-ID | <r1up93$p7n$1@dont-email.me> |
| In reply to | #149948 |
On 11/02/2020 17:32, James Kuyper wrote: > "The array-subscript [ ] operator ... may be used in the creation of an address constant, but the value of an object may not be accessed by the use of [that] operator." (6,6p9). > Right. So since the expression "offsetof(struct S, a[i])" has to access the object "i" in order to calculate the address (or the offset, in this case), it is disallowed?
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2020-02-11 19:24 +0100 |
| Message-ID | <r1urgn$856$1@gioia.aioe.org> |
| In reply to | #149951 |
On 2/11/2020 6:46 PM, David Brown wrote: > On 11/02/2020 17:32, James Kuyper wrote: >> "The array-subscript [ ] operator ... may be used in the creation of >> an address constant, but the value of an object may not be accessed by >> the use of [that] operator." (6,6p9). >> > > Right. So since the expression "offsetof(struct S, a[i])" has to access > the object "i" in order to calculate the address (or the offset, in this > case), it is disallowed? > It sound to me like this part says the address constant creation /is/ allowed, since the object is not accessed, i.e. its address is not dereferenced. (This is obvious in the common implementation of offsetof that places S at address 0). But the problem still holds for the other part of the specification of offsetof, the one pointed out by Guillaume, which is my main doubt as well: Guillaume wrote: > the standard defines offsetof() with its second parameter being a struct member designator. a[i] is not, unless I'm mistaken, a member designator, but an expression derived from one. Thus you'd be using offsetof() with (IMO) an invalid parameter If you look at 7.19p3, the specification of offsetof(type, member-designator) has requirements for both /type/ and /member-designator/ The requirement for /member-designator/ uses the wording of the Guillaume quote above, the requirement for /type/ refers to the creation of an address constant, which is what James' comment is about.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2020-02-11 19:36 +0100 |
| Message-ID | <r1us76$bcd$1@gioia.aioe.org> |
| In reply to | #149953 |
On 2/11/2020 7:24 PM, Manfred wrote: > On 2/11/2020 6:46 PM, David Brown wrote: >> On 11/02/2020 17:32, James Kuyper wrote: >>> "The array-subscript [ ] operator ... may be used in the creation of >>> an address constant, but the value of an object may not be accessed >>> by the use of [that] operator." (6,6p9). >>> >> >> Right. So since the expression "offsetof(struct S, a[i])" has to >> access the object "i" in order to calculate the address (or the >> offset, in this case), it is disallowed? >> > > It sound to me like this part says the address constant creation /is/ > allowed, since the object is not accessed, i.e. its address is not > dereferenced. (This is obvious in the common implementation of offsetof > that places S at address 0). > Hmm. doubting myself here - "i" is not a constant, thus &s.a[i] is not constant either, so how can it be an address constant? Which is probably another derivation of your conclusion above.
[toc] | [prev] | [next] | [standalone]
| From | James Kuyper <jameskuyper@alumni.caltech.edu> |
|---|---|
| Date | 2020-02-11 22:50 -0500 |
| Message-ID | <r1vsm9$o3p$1@dont-email.me> |
| In reply to | #149953 |
On 2/11/20 1:24 PM, Manfred wrote: > On 2/11/2020 6:46 PM, David Brown wrote: >> On 11/02/2020 17:32, James Kuyper wrote: >>> "The array-subscript [ ] operator ... may be used in the creation of >>> an address constant, but the value of an object may not be accessed by >>> the use of [that] operator." (6,6p9). >>> >> >> Right. So since the expression "offsetof(struct S, a[i])" has to access >> the object "i" in order to calculate the address (or the offset, in this >> case), it is disallowed? >> > > It sound to me like this part says the address constant creation /is/ > allowed, since the object is not accessed, i.e. its address is not > dereferenced. The relevant object is "i", not S. And it's the value of the object, not it's address, which, if accessed, violates that rule. The value stored in 'i' is needed to determine that offset, so this construct does violate that rule.
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2020-02-12 13:53 +0100 |
| Message-ID | <r20sh0$19n3$1@gioia.aioe.org> |
| In reply to | #149961 |
On 2/12/2020 4:50 AM, James Kuyper wrote: > On 2/11/20 1:24 PM, Manfred wrote: >> On 2/11/2020 6:46 PM, David Brown wrote: >>> On 11/02/2020 17:32, James Kuyper wrote: >>>> "The array-subscript [ ] operator ... may be used in the creation of >>>> an address constant, but the value of an object may not be accessed by >>>> the use of [that] operator." (6,6p9). >>>> >>> >>> Right. So since the expression "offsetof(struct S, a[i])" has to access >>> the object "i" in order to calculate the address (or the offset, in this >>> case), it is disallowed? >>> >> >> It sound to me like this part says the address constant creation /is/ >> allowed, since the object is not accessed, i.e. its address is not >> dereferenced. > > The relevant object is "i", not S. And it's the value of the object, not > it's address, which, if accessed, violates that rule. The value stored > in 'i' is needed to determine that offset, so this construct does > violate that rule. > Yes, in fact in my follow-up I had an afterthought about "i" as well - being an "object" whose value is accessed is substantially incompatible with a constant expression (which by definition can be evaluated at compile time and may have no storage) - this is to say that the requirement that "an object may not be accessed" is to guarantee that an address constant is a constant expression (p6.6)
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2020-02-18 01:43 -0800 |
| Message-ID | <86y2t0dydh.fsf@linuxsc.com> |
| In reply to | #149961 |
James Kuyper <jameskuyper@alumni.caltech.edu> writes: > On 2/11/20 1:24 PM, Manfred wrote: > >> On 2/11/2020 6:46 PM, David Brown wrote: >> >>> On 11/02/2020 17:32, James Kuyper wrote: >>> >>>> "The array-subscript [ ] operator ... may be used in the creation of >>>> an address constant, but the value of an object may not be accessed by >>>> the use of [that] operator." (6,6p9). >>> >>> Right. So since the expression "offsetof(struct S, a[i])" has to access >>> the object "i" in order to calculate the address (or the offset, in this >>> case), it is disallowed? >> >> It sound to me like this part says the address constant creation /is/ >> allowed, since the object is not accessed, i.e. its address is not >> dereferenced. > > The relevant object is "i", not S. And it's the value of the object, not > it's address, which, if accessed, violates that rule. The value stored > in 'i' is needed to determine that offset, so this construct does > violate that rule. It isn't the use of [] that accesses an object. It is the lvalue conversion of 'i' that accesses an object.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <tr.17687@z991.linuxsc.com> |
|---|---|
| Date | 2020-02-18 01:39 -0800 |
| Message-ID | <8636b8fd3w.fsf@linuxsc.com> |
| In reply to | #149946 |
Guillaume <message@bottle.org> writes:
> Le 11/02/2020 at 15:31, David Brown a ecrit:
>
>> #include <stddef.h>
>>
>> struct S {
>> int a[10];
>> };
>>
>> int test(int i) {
>> return offsetof(struct S, a[i]);
>> }
>>
>>
>> Is this allowed in standard C? [...]
Undefined behavior, as was pointed out downthread, because of a
non-constant address calculation. However, leading into the next
point, what if the address calculation were suitably constant, and so
satisfies the stipulation that "the expression &(t.member-designator)
evaluates to an address constant"?
> [...]
>
> There's just a small "but": the standard defines offsetof() with its
> second parameter being a struct member designator. a[i] is not, unless
> I'm mistaken, a member designator, but an expression derived from
> one. Thus you'd be using offsetof() with (IMO) an invalid parameter,
> and this should be reasonably rejected by a conforming compiler. It
> looks like some compilers choose to make this implementation-defined
> instead. Just my opinion on this.
A strict reading of the text of the Standard supports this conclusion,
even if the array index expression were suitably constant. The
Standard consistently uses the term "stucture member" to mean an
first-level subobject, and not a sub-subobject for any level beyond
the first. The safest course here would use
offsetof( struct S, a )
and add in the adjustment for a[i] using sizeof and a multiplication.
Probably this reading is not what was intended for offsetof(), but I
haven't seen any evidence of that. (Fair disclosure: I haven't made
any special effort to find any either.) But a good rule to follow in
cases where the Standard isn't 100% definitive is to err on the side
of caution, choosing the most conservative path reasonably available.
And here that is easy to do, by using the simpler call to offsetof()
shown above, and adjusting the result with a sizeof, etc.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2020-02-11 16:56 +0000 |
| Message-ID | <f1B0G.422048$lJ.1756@fx27.am4> |
| In reply to | #149945 |
On 11/02/2020 14:31, David Brown wrote:
> #include <stddef.h>
>
> struct S {
> int a[10];
> };
>
> int test(int i) {
> return offsetof(struct S, a[i]);
> }
>
>
> Is this allowed in standard C? It works in most compilers I tried (even
> in the most pedantic modes I checked on gcc), but failed in one embedded
> compiler. According to the standard, "offsetof" expands to "an integer
> constant expression", and "&s.a[i]" must evaluate to an address constant
> (where "s" is an object of type "struct S").
>
> So by my reading, the standard C does not require the expression in
> "test" to be valid, and allows a conforming compiler to reject it.
> Equally, it does not require a diagnostic, and allows a conforming
> compiler to accept it without complaint.
>
I tried this with the expected results on the handful of compilers tested:
--------------------
#include <stdio.h>
#include <stddef.h>
struct S {
int a[10];
};
int test(int i) {
return offsetof(struct S, a[i]);
}
int main(void) {
for (int i=0; i<10; ++i)
printf("Offset of A[%d] is %d\n",i,test(i));
}
------------------
I say 'expected' but I thought my bcc at least would fail, because I
consider 'offsetof' a device to return the offset of a struct member,
which is always going to be a compile-time constant.
It works in my case because offsetof is defined as:
#define offsetof(a,b) (size_t) &( ((a*)0) -> b)
And the body of test() becomes:
return(size_t)&(((struct S*)0)->a[i]);
Presumably your odd compiler tries to be too clever.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-02-11 18:49 +0100 |
| Message-ID | <r1upf6$rrc$1@dont-email.me> |
| In reply to | #149950 |
On 11/02/2020 17:56, Bart wrote:
> On 11/02/2020 14:31, David Brown wrote:
>> #include <stddef.h>
>>
>> struct S {
>> int a[10];
>> };
>>
>> int test(int i) {
>> return offsetof(struct S, a[i]);
>> }
>>
>>
>> Is this allowed in standard C? It works in most compilers I tried (even
>> in the most pedantic modes I checked on gcc), but failed in one embedded
>> compiler. According to the standard, "offsetof" expands to "an integer
>> constant expression", and "&s.a[i]" must evaluate to an address constant
>> (where "s" is an object of type "struct S").
>>
>> So by my reading, the standard C does not require the expression in
>> "test" to be valid, and allows a conforming compiler to reject it.
>> Equally, it does not require a diagnostic, and allows a conforming
>> compiler to accept it without complaint.
>>
>
> I tried this with the expected results on the handful of compilers tested:
>
> --------------------
> #include <stdio.h>
> #include <stddef.h>
>
> struct S {
> int a[10];
> };
>
> int test(int i) {
> return offsetof(struct S, a[i]);
> }
>
> int main(void) {
> for (int i=0; i<10; ++i)
> printf("Offset of A[%d] is %d\n",i,test(i));
> }
> ------------------
>
> I say 'expected' but I thought my bcc at least would fail, because I
> consider 'offsetof' a device to return the offset of a struct member,
> which is always going to be a compile-time constant.
>
> It works in my case because offsetof is defined as:
>
> #define offsetof(a,b) (size_t) &( ((a*)0) -> b)
Yes, that's a common way to define "offsetof". It involves behaviour
that is undefined in the C standard (there is AFAIK no way to write the
offsetof macro using only standards-defined C), but as long as the
compiler is happy with it, it's no problem.
>
> And the body of test() becomes:
>
> return(size_t)&(((struct S*)0)->a[i]);
>
> Presumably your odd compiler tries to be too clever.
It sounds like it is justified in rejecting the code, while most
compilers are more lenient than the standard requires.
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2020-02-11 21:00 +0100 |
| Message-ID | <r1v150$nb7$1@news.albasani.net> |
| In reply to | #149945 |
How about this: #include <stddef.h> #define array_offsetof(type, member, index) (size_t)(offsetof(type, member) + sizeof(((type *)NULL)->##member[0]) * index)
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2020-02-11 20:13 +0000 |
| Message-ID | <YVD0G.293006$j92.144407@fx14.am4> |
| In reply to | #149955 |
On 11/02/2020 20:00, Bonita Montero wrote:
> How about this:
>
> #include <stddef.h>
> #define array_offsetof(type, member, index) (size_t)(offsetof(type,
> member) + sizeof(((type *)NULL)->##member[0]) * index)
Did you test it? It fails on most (not all) compilers including gcc.
This version seems to work on all the ones I tried:
#define array_offsetof(type, member, index) \
(offsetof(type, member) + sizeof( ((type *)0)->member[0]) * index)
It's invoked like this:
return array_offsetof(struct S, a, i);
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2020-02-11 21:24 +0100 |
| Message-ID | <r1v2hi$f30$1@news.albasani.net> |
| In reply to | #149956 |
>> How about this: >> >> #include <stddef.h> >> #define array_offsetof(type, member, index) (size_t)(offsetof(type, >> member) + sizeof(((type *)NULL)->##member[0]) * index) > Did you test it? It fails on most (not all) compilers including gcc. > This version seems to work on all the ones I tried: > #define array_offsetof(type, member, index) \ > (offsetof(type, member) + sizeof( ((type *)0)->member[0]) * index) > It's invoked like this: > return array_offsetof(struct S, a, i); Don't know why, but my version works when compiled as C++ and not as C. I thought that might be o.k. for C also. But I'm wondering why you won't have to write (struct type *) but (type *). Did you typedef ?
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2020-02-11 20:33 +0000 |
| Message-ID | <IcE0G.98236$cW.40397@fx16.am4> |
| In reply to | #149957 |
On 11/02/2020 20:24, Bonita Montero wrote: >>> How about this: >>> >>> #include <stddef.h> >>> #define array_offsetof(type, member, index) (size_t)(offsetof(type, >>> member) + sizeof(((type *)NULL)->##member[0]) * index) > >> Did you test it? It fails on most (not all) compilers including gcc. >> This version seems to work on all the ones I tried: >> #define array_offsetof(type, member, index) \ >> (offsetof(type, member) + sizeof( ((type *)0)->member[0]) * index) >> It's invoked like this: >> return array_offsetof(struct S, a, i); > > Don't know why, but my version works when compiled as C++ and not > as C. I thought that might be o.k. for C also. > But I'm wondering why you won't have to write (struct type *) but > (type *). Did you typedef ? No. That means that in C, the 'type' of the stuct is 'struct S' rather than just 'S' if you do this: typedef struct S S;
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2020-02-11 21:39 +0100 |
| Message-ID | <r1v3e3$dvl$1@news.albasani.net> |
| In reply to | #149958 |
>>>> How about this: >>>> >>>> #include <stddef.h> >>>> #define array_offsetof(type, member, index) (size_t)(offsetof(type, >>>> member) + sizeof(((type *)NULL)->##member[0]) * index) >> >>> Did you test it? It fails on most (not all) compilers including gcc. >>> This version seems to work on all the ones I tried: >>> #define array_offsetof(type, member, index) \ >>> (offsetof(type, member) + sizeof( ((type *)0)->member[0]) * index) >>> It's invoked like this: >>> return array_offsetof(struct S, a, i); >> >> Don't know why, but my version works when compiled as C++ and not >> as C. I thought that might be o.k. for C also. >> But I'm wondering why you won't have to write (struct type *) but >> (type *). Did you typedef ? > > No. That means that in C, the 'type' of the stuct is 'struct S' rather > than just 'S' if you do this: > > typedef struct S S; Of course, but you wrote "((type *)0)->member[0])" without struct. So you rely on a duplicate typedef.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2020-02-11 20:48 +0000 |
| Message-ID | <sqE0G.342067$UPz1.332158@fx15.am4> |
| In reply to | #149959 |
On 11/02/2020 20:39, Bonita Montero wrote:
>>>>> How about this:
>>>>>
>>>>> #include <stddef.h>
>>>>> #define array_offsetof(type, member, index) (size_t)(offsetof(type,
>>>>> member) + sizeof(((type *)NULL)->##member[0]) * index)
>>>
>>>> Did you test it? It fails on most (not all) compilers including gcc.
>>>> This version seems to work on all the ones I tried:
>>>> #define array_offsetof(type, member, index) \
>>>> (offsetof(type, member) + sizeof( ((type *)0)->member[0]) * index)
>>>> It's invoked like this:
>>>> return array_offsetof(struct S, a, i);
>>>
>>> Don't know why, but my version works when compiled as C++ and not
>>> as C. I thought that might be o.k. for C also.
>>> But I'm wondering why you won't have to write (struct type *) but
>>> (type *). Did you typedef ?
>>
>> No. That means that in C, the 'type' of the stuct is 'struct S' rather
>> than just 'S' if you do this:
>>
>> typedef struct S S;
>
> Of course, but you wrote "((type *)0)->member[0])" without struct.
> So you rely on a duplicate typedef.
'type' is the name of a macro parameter. The macro argument was 'struct S':
return array_offsetof(struct S, a, i);
I could have chosen to insert 'struct' into the macro body, but then it
could only be invoked with a struct tag name, not either 'struct tag' or
a typedefed struct.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-02-12 10:56 +0100 |
| Message-ID | <r20i4t$qjo$1@dont-email.me> |
| In reply to | #149955 |
On 11/02/2020 21:00, Bonita Montero wrote: > How about this: > > #include <stddef.h> > #define array_offsetof(type, member, index) (size_t)(offsetof(type, > member) + sizeof(((type *)NULL)->##member[0]) * index) I have no problem finding the offset to the array item. My question was about whether it can be done portably using offsetof directly - was this a bug or limitation in the one particular compiler, or are other compilers being helpfully lenient? (The conclusion seems to be the later.)
[toc] | [prev] | [next] | [standalone]
| From | Bonita Montero <Bonita.Montero@gmail.com> |
|---|---|
| Date | 2020-02-12 14:07 +0100 |
| Message-ID | <r20tan$b9b$2@news.albasani.net> |
| In reply to | #149964 |
> I have no problem finding the offset to the array item. ... So your question is a waste of time.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.c
csiph-web