Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #44630 > unrolled thread
| Started by | Melzzzzz <mel@zzzzz.com> |
|---|---|
| First post | 2016-08-31 14:59 +0200 |
| Last post | 2016-09-05 21:25 +0100 |
| Articles | 20 on this page of 123 — 25 participants |
Back to article view | Back to comp.lang.c++
This will work or not? Melzzzzz <mel@zzzzz.com> - 2016-08-31 14:59 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-08-31 15:20 +0200
Re: This will work or not? mark <mark@invalid.invalid> - 2016-08-31 16:05 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-08-31 16:19 +0200
Re: This will work or not? scott@slp53.sl.home (Scott Lurndal) - 2016-08-31 14:20 +0000
Re: This will work or not? Bo Persson <bop@gmb.dk> - 2016-08-31 18:53 +0200
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-01 09:03 -0700
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-01 22:45 +0200
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-01 18:08 -0700
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 09:24 +0200
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 06:31 -0700
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-04 20:19 +0200
Re: This will work or not? Manfred <noname@invalid.add> - 2016-08-31 15:45 +0200
Re: This will work or not? Melzzzzz <mel@zzzzz.com> - 2016-08-31 15:59 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-08-31 16:22 +0200
Re: This will work or not? Manfred <noname@invalid.add> - 2016-08-31 17:06 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-08-31 19:29 +0200
Re: This will work or not? Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2016-08-31 21:52 +0100
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-01 09:07 +0200
Re: This will work or not? Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2016-09-01 12:30 +0100
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-01 09:01 -0700
Re: This will work or not? Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2016-09-01 18:16 +0100
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-01 18:37 -0700
Re: This will work or not? Chris Vine <chris@cvine--nospam--.freeserve.co.uk> - 2016-09-02 10:42 +0100
Re: This will work or not? Tim Rentsch <txr@alumni.caltech.edu> - 2016-09-04 06:59 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-08-31 23:17 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-01 09:35 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-01 15:34 -0400
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-01 13:50 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-01 21:01 -0400
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-01 19:02 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-01 22:17 -0400
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-02 08:19 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 12:39 -0400
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-02 12:26 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 16:38 -0400
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-02 13:51 -0700
Re: This will work or not? me <crisdunbar@gmail.com> - 2016-09-02 14:16 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 19:58 -0400
Re: This will work or not? Paavo Helde <myfirstname@osa.pri.ee> - 2016-09-02 23:56 +0300
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-03 17:58 +0200
Re: This will work or not? Manfred <noname@invalid.add> - 2016-09-02 11:41 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 12:27 +0200
Re: This will work or not? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-02 12:37 +0100
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 17:39 +0200
Re: This will work or not? Melzzzzz <mel@zzzzz.com> - 2016-09-02 17:40 +0200
Re: This will work or not? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-02 16:54 +0100
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 20:22 +0200
Re: This will work or not? Richard Damon <Richard@Damon-Family.org> - 2016-09-02 08:04 -0400
Re: This will work or not? BartC <bc@freeuk.com> - 2016-09-02 13:51 +0100
Re: This will work or not? Richard Damon <Richard@Damon-Family.org> - 2016-09-02 21:48 -0400
Re: This will work or not? Manfred <noname@invalid.add> - 2016-09-02 15:17 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 17:46 +0200
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-01 23:14 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-01 21:02 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 09:35 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 08:50 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 17:59 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 12:49 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-02 20:36 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-02 16:32 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-03 18:08 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-03 18:25 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-03 23:51 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-03 21:48 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 03:48 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-03 23:05 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 05:02 +0100
Re: This will work or not? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-09-04 10:57 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 09:40 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 16:39 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 12:46 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 17:51 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 13:07 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 18:37 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 17:16 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 22:23 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 18:54 -0400
Re: This will work or not? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-09-04 09:58 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 13:08 -0400
Re: This will work or not? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-09-04 10:21 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 17:18 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 22:24 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 18:56 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-05 00:27 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 22:53 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-05 18:18 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-05 15:27 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-05 20:32 +0100
Re: This will work or not? woodbrian77@gmail.com - 2016-09-05 14:07 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-05 18:15 -0400
Re: This will work or not? Ike Naar <ike@iceland.freeshell.org> - 2016-09-05 20:12 +0000
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-05 22:05 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-05 18:16 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-06 08:47 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-06 09:12 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-06 16:31 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-06 11:20 -0400
Re: This will work or not? bighe.trole@gmail.com - 2016-09-04 18:55 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 22:55 -0400
Re: This will work or not? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-09-04 17:17 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 22:57 -0400
Re: This will work or not? "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-09-05 11:20 -0700
Re: This will work or not? Luuk <luuk@invalid.lan> - 2016-09-04 18:54 +0200
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 17:59 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 13:08 -0400
Re: This will work or not? David Brown <david.brown@hesbynett.no> - 2016-09-04 20:25 +0200
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 17:20 -0400
Re: This will work or not? Öö Tiib <ootiib@hot.ee> - 2016-09-04 02:36 -0700
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-04 09:41 -0400
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-03 21:49 -0400
Re: This will work or not? Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk> - 2016-09-04 03:49 +0100
Re: This will work or not? Jerry Stuckle <jstucklex@attglobal.net> - 2016-09-03 23:06 -0400
Re: This will work or not? woodbrian77@gmail.com - 2016-09-03 21:16 -0700
Re: This will work or not? Vir Campestris <vir.campestris@invalid.invalid> - 2016-08-31 21:08 +0100
Re: This will work or not? "Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com> - 2016-09-01 02:28 +0200
Re: This will work or not? Öö Tiib <ootiib@hot.ee> - 2016-09-01 01:28 -0700
Re: This will work or not? "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-09-02 12:06 -0700
Re: This will work or not? Öö Tiib <ootiib@hot.ee> - 2016-09-05 02:21 -0700
Re: This will work or not? Melzzzzz <mel@zzzzz.com> - 2016-09-05 13:38 +0200
Re: This will work or not? Juha Nieminen <nospam@thanks.invalid> - 2016-09-05 11:34 +0000
Re: This will work or not? Melzzzzz <mel@zzzzz.com> - 2016-09-05 13:36 +0200
Re: This will work or not? Vir Campestris <vir.campestris@invalid.invalid> - 2016-09-05 21:25 +0100
Page 1 of 7 [1] 2 3 4 5 6 7 Next page →
| From | Melzzzzz <mel@zzzzz.com> |
|---|---|
| Date | 2016-08-31 14:59 +0200 |
| Subject | This will work or not? |
| Message-ID | <20160831145918.45a0c396@maxa-pc> |
Code in question is like this:
struct Problem{
uint32_t a;
uint32_t b;
uint64_t c;
uint32_t d;
bool check_it() {
for (uint32_t* i = &a;i != &d; ++i)
if (*i>0) return true;
return false;
}
};
I am not sure if this will work, so if someone has clear explanation
why it will work (or not) , I would be grateful.
[toc] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-08-31 15:20 +0200 |
| Message-ID | <nq6ljf$65e$1@dont-email.me> |
| In reply to | #44630 |
On 31/08/16 14:59, Melzzzzz wrote:
> Code in question is like this:
>
> struct Problem{
> uint32_t a;
> uint32_t b;
> uint64_t c;
> uint32_t d;
> bool check_it() {
> for (uint32_t* i = &a;i != &d; ++i)
> if (*i>0) return true;
> return false;
> }
>
> };
>
> I am not sure if this will work, so if someone has clear explanation
> why it will work (or not) , I would be grateful.
>
I don't think you are guaranteed that a, b, c, and d follow each other
in the structure layout (though it is very likely to be the case). With
a pointer to a single item &a, incrementing the pointer is undefined
behaviour - as is accessing *i. And accessing the uint64_t member using
an uint32_t* pointer contradicts aliasing restrictions.
All in all, the compiler is free to assume that this code is full of
undefined behaviour, therefore you don't really care what it does -
therefore it can all be optimised to "return true", "return false", or
even "launch nasal daemons". (This last option is legal for the
compiler, but thankfully unlikely in practice.)
You can make it legal with:
struct Problem {
union {
struct {
uint32_t a;
uint32_t b;
uint64_t c;
uint32_t d;
}
uint32_t as_array[5];
}
bool check_it() {
for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
if (*i > 0) return true;
return false;
}
}
(Any issues regarding anonymous unions/structs are left as an exercise
for the reader :-)
[toc] | [prev] | [next] | [standalone]
| From | mark <mark@invalid.invalid> |
|---|---|
| Date | 2016-08-31 16:05 +0200 |
| Message-ID | <nq6o72$f08$1@dont-email.me> |
| In reply to | #44631 |
On 2016-08-31 15:20, David Brown wrote:
> On 31/08/16 14:59, Melzzzzz wrote:
>> > Code in question is like this:
>> >
>> > struct Problem{
>> > uint32_t a;
>> > uint32_t b;
>> > uint64_t c;
>> > uint32_t d;
>> > bool check_it() {
>> > for (uint32_t* i = &a;i != &d; ++i)
>> > if (*i>0) return true;
>> > return false;
>> > }
>> >
>> > };
>> >
>> > I am not sure if this will work, so if someone has clear explanation
>> > why it will work (or not) , I would be grateful.
>> >
> I don't think you are guaranteed that a, b, c, and d follow each other
> in the structure layout (though it is very likely to be the case). With
> a pointer to a single item &a, incrementing the pointer is undefined
> behaviour - as is accessing *i.
I don't think so. My reading of the standard is that code would have
well-defined and legal behavior if c was uint32_t and no padding is used.
C++14 5.7 (Additive operators):
<<<
84) An object that is not an array element is considered to belong to a
single-element array for this purpose
>>>
It is legal to point 1 element past the array size. So "&a + 1" is legal
and will in turn point to another valid uint32_t.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-08-31 16:19 +0200 |
| Message-ID | <nq6p1r$hi6$1@dont-email.me> |
| In reply to | #44634 |
On 31/08/16 16:05, mark wrote:
> On 2016-08-31 15:20, David Brown wrote:
>> On 31/08/16 14:59, Melzzzzz wrote:
>>> > Code in question is like this:
>>> >
>>> > struct Problem{
>>> > uint32_t a;
>>> > uint32_t b;
>>> > uint64_t c;
>>> > uint32_t d;
>>> > bool check_it() {
>>> > for (uint32_t* i = &a;i != &d; ++i)
>>> > if (*i>0) return true;
>>> > return false;
>>> > }
>>> >
>>> > };
>>> >
>>> > I am not sure if this will work, so if someone has clear explanation
>>> > why it will work (or not) , I would be grateful.
>>> >
>> I don't think you are guaranteed that a, b, c, and d follow each other
>> in the structure layout (though it is very likely to be the case). With
>> a pointer to a single item &a, incrementing the pointer is undefined
>> behaviour - as is accessing *i.
>
> I don't think so. My reading of the standard is that code would have
> well-defined and legal behavior if c was uint32_t and no padding is used.
>
> C++14 5.7 (Additive operators):
> <<<
> 84) An object that is not an array element is considered to belong to a
> single-element array for this purpose
>>>>
>
> It is legal to point 1 element past the array size. So "&a + 1" is legal
> and will in turn point to another valid uint32_t.
No, I don't think that is right. "&a + 1" is legal - but it does not
point to another valid uint32_t, and you can't dereference it. You are
allowed to make a pointer move one step off the end of an array, so that
you can make comparisons with "<" in your loops. But you can't use the
pointer for accessing anything.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2016-08-31 14:20 +0000 |
| Message-ID | <lIBxz.56431$uc6.18392@fx41.iad> |
| In reply to | #44631 |
David Brown <david.brown@hesbynett.no> writes:
>On 31/08/16 14:59, Melzzzzz wrote:
>> Code in question is like this:
>>
>> struct Problem{
>> uint32_t a;
>> uint32_t b;
>> uint64_t c;
>> uint32_t d;
>> bool check_it() {
>> for (uint32_t* i = &a;i != &d; ++i)
>> if (*i>0) return true;
>> return false;
>> }
>>
>> };
>>
>> I am not sure if this will work, so if someone has clear explanation
>> why it will work (or not) , I would be grateful.
>>
>
>I don't think you are guaranteed that a, b, c, and d follow each other
>in the structure layout (though it is very likely to be the case).
It is guaranteed that the fields will be ordered in memory
as it in the source. It is not guaranteed that there will not be
padding between the fields unless a compiler dependent mechanism to
specified "packed" for the struct is present.
[toc] | [prev] | [next] | [standalone]
| From | Bo Persson <bop@gmb.dk> |
|---|---|
| Date | 2016-08-31 18:53 +0200 |
| Message-ID | <e2ogbcFb2uiU1@mid.individual.net> |
| In reply to | #44631 |
On 2016-08-31 15:20, David Brown wrote:
> On 31/08/16 14:59, Melzzzzz wrote:
>> Code in question is like this:
>>
>> struct Problem{
>> uint32_t a;
>> uint32_t b;
>> uint64_t c;
>> uint32_t d;
>> bool check_it() {
>> for (uint32_t* i = &a;i != &d; ++i)
>> if (*i>0) return true;
>> return false;
>> }
>>
>> };
>>
>> I am not sure if this will work, so if someone has clear explanation
>> why it will work (or not) , I would be grateful.
>>
>
> I don't think you are guaranteed that a, b, c, and d follow each other
> in the structure layout (though it is very likely to be the case). With
> a pointer to a single item &a, incrementing the pointer is undefined
> behaviour - as is accessing *i. And accessing the uint64_t member using
> an uint32_t* pointer contradicts aliasing restrictions.
>
> All in all, the compiler is free to assume that this code is full of
> undefined behaviour, therefore you don't really care what it does -
> therefore it can all be optimised to "return true", "return false", or
> even "launch nasal daemons". (This last option is legal for the
> compiler, but thankfully unlikely in practice.)
>
> You can make it legal with:
>
> struct Problem {
> union {
> struct {
> uint32_t a;
> uint32_t b;
> uint64_t c;
> uint32_t d;
> }
> uint32_t as_array[5];
> }
> bool check_it() {
> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
> if (*i > 0) return true;
> return false;
> }
> }
>
> (Any issues regarding anonymous unions/structs are left as an exercise
> for the reader :-)
>
This might work in C, but a problem is that the C++ standard says:
9.3 Unions
"In a union, a non-static data member is active if its name refers to an
object whose lifetime has begun and has not ended (3.8). At most one of
the non-static data members of an object of union type can be active at
any time, that is, the value of at most one of the non-static data
members can be stored in a union at any time. "
So, if the struct with a, b, c, and d is active, as_array is not
"stored" and cannot be read. You can't read an object that isn't there!
Bo Persson
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-01 09:03 -0700 |
| Message-ID | <kfny43bobe9.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #44639 |
Bo Persson <bop@gmb.dk> writes:
> On 2016-08-31 15:20, David Brown wrote:
>> On 31/08/16 14:59, Melzzzzz wrote:
>>> Code in question is like this:
>>>
>>> struct Problem{
>>> uint32_t a;
>>> uint32_t b;
>>> uint64_t c;
>>> uint32_t d;
>>> bool check_it() {
>>> for (uint32_t* i = &a;i != &d; ++i)
>>> if (*i>0) return true;
>>> return false;
>>> }
>>>
>>> };
>>>
>>> I am not sure if this will work, so if someone has clear explanation
>>> why it will work (or not) , I would be grateful.
>>
>> I don't think you are guaranteed that a, b, c, and d follow each other
>> in the structure layout (though it is very likely to be the case). With
>> a pointer to a single item &a, incrementing the pointer is undefined
>> behaviour - as is accessing *i. And accessing the uint64_t member using
>> an uint32_t* pointer contradicts aliasing restrictions.
>>
>> All in all, the compiler is free to assume that this code is full of
>> undefined behaviour, therefore you don't really care what it does -
>> therefore it can all be optimised to "return true", "return false", or
>> even "launch nasal daemons". (This last option is legal for the
>> compiler, but thankfully unlikely in practice.)
>>
>> You can make it legal with:
>>
>> struct Problem {
>> union {
>> struct {
>> uint32_t a;
>> uint32_t b;
>> uint64_t c;
>> uint32_t d;
>> }
>> uint32_t as_array[5];
>> }
>> bool check_it() {
>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>> if (*i > 0) return true;
>> return false;
>> }
>> }
>>
>> (Any issues regarding anonymous unions/structs are left as an exercise
>> for the reader :-)
>
> This might work in C, but a problem is that the C++ standard says:
>
> 9.3 Unions
> "In a union, a non-static data member is active if its name refers to
> an object whose lifetime has begun and has not ended (3.8). At most
> one of the non-static data members of an object of union type can be
> active at any time, that is, the value of at most one of the
> non-static data members can be stored in a union at any time. "
>
> So, if the struct with a, b, c, and d is active, as_array is not
> "stored" and cannot be read. You can't read an object that isn't
> there!
So this is another way that C++ is not upwards compatible from
C?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-01 22:45 +0200 |
| Message-ID | <nqa40d$a98$1@dont-email.me> |
| In reply to | #44684 |
On 01/09/16 18:03, Tim Rentsch wrote:
> Bo Persson <bop@gmb.dk> writes:
>
>> On 2016-08-31 15:20, David Brown wrote:
>>> On 31/08/16 14:59, Melzzzzz wrote:
>>>> Code in question is like this:
>>>>
>>>> struct Problem{
>>>> uint32_t a;
>>>> uint32_t b;
>>>> uint64_t c;
>>>> uint32_t d;
>>>> bool check_it() {
>>>> for (uint32_t* i = &a;i != &d; ++i)
>>>> if (*i>0) return true;
>>>> return false;
>>>> }
>>>>
>>>> };
>>>>
>>>> I am not sure if this will work, so if someone has clear explanation
>>>> why it will work (or not) , I would be grateful.
>>>
>>> I don't think you are guaranteed that a, b, c, and d follow each other
>>> in the structure layout (though it is very likely to be the case). With
>>> a pointer to a single item &a, incrementing the pointer is undefined
>>> behaviour - as is accessing *i. And accessing the uint64_t member using
>>> an uint32_t* pointer contradicts aliasing restrictions.
>>>
>>> All in all, the compiler is free to assume that this code is full of
>>> undefined behaviour, therefore you don't really care what it does -
>>> therefore it can all be optimised to "return true", "return false", or
>>> even "launch nasal daemons". (This last option is legal for the
>>> compiler, but thankfully unlikely in practice.)
>>>
>>> You can make it legal with:
>>>
>>> struct Problem {
>>> union {
>>> struct {
>>> uint32_t a;
>>> uint32_t b;
>>> uint64_t c;
>>> uint32_t d;
>>> }
>>> uint32_t as_array[5];
>>> }
>>> bool check_it() {
>>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>>> if (*i > 0) return true;
>>> return false;
>>> }
>>> }
>>>
>>> (Any issues regarding anonymous unions/structs are left as an exercise
>>> for the reader :-)
>>
>> This might work in C, but a problem is that the C++ standard says:
>>
>> 9.3 Unions
>> "In a union, a non-static data member is active if its name refers to
>> an object whose lifetime has begun and has not ended (3.8). At most
>> one of the non-static data members of an object of union type can be
>> active at any time, that is, the value of at most one of the
>> non-static data members can be stored in a union at any time. "
>>
>> So, if the struct with a, b, c, and d is active, as_array is not
>> "stored" and cannot be read. You can't read an object that isn't
>> there!
>
> So this is another way that C++ is not upwards compatible from
> C?
>
In theory, yes. But the platforms that support C++ are much more
"normal" than those that support C, and there are far fewer C++
compilers around. If all these C++ compilers support type punning
through unions, as gcc and clang do, then there will be no
incompatibility in practice.
And perhaps someday someone will tidy up such missing points from the
C++ standards so that they catch up with the changes in later C standards.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-01 18:08 -0700 |
| Message-ID | <kfntwdznm5b.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #44706 |
David Brown <david.brown@hesbynett.no> writes:
> On 01/09/16 18:03, Tim Rentsch wrote:
>> Bo Persson <bop@gmb.dk> writes:
>>
>>> On 2016-08-31 15:20, David Brown wrote:
>>>> On 31/08/16 14:59, Melzzzzz wrote:
>>>>> Code in question is like this:
>>>>>
>>>>> struct Problem{
>>>>> uint32_t a;
>>>>> uint32_t b;
>>>>> uint64_t c;
>>>>> uint32_t d;
>>>>> bool check_it() {
>>>>> for (uint32_t* i = &a;i != &d; ++i)
>>>>> if (*i>0) return true;
>>>>> return false;
>>>>> }
>>>>>
>>>>> };
>>>>>
>>>>> I am not sure if this will work, so if someone has clear explanation
>>>>> why it will work (or not) , I would be grateful.
>>>>
>>>> I don't think you are guaranteed that a, b, c, and d follow each other
>>>> in the structure layout (though it is very likely to be the case). With
>>>> a pointer to a single item &a, incrementing the pointer is undefined
>>>> behaviour - as is accessing *i. And accessing the uint64_t member using
>>>> an uint32_t* pointer contradicts aliasing restrictions.
>>>>
>>>> All in all, the compiler is free to assume that this code is full of
>>>> undefined behaviour, therefore you don't really care what it does -
>>>> therefore it can all be optimised to "return true", "return false", or
>>>> even "launch nasal daemons". (This last option is legal for the
>>>> compiler, but thankfully unlikely in practice.)
>>>>
>>>> You can make it legal with:
>>>>
>>>> struct Problem {
>>>> union {
>>>> struct {
>>>> uint32_t a;
>>>> uint32_t b;
>>>> uint64_t c;
>>>> uint32_t d;
>>>> }
>>>> uint32_t as_array[5];
>>>> }
>>>> bool check_it() {
>>>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>>>> if (*i > 0) return true;
>>>> return false;
>>>> }
>>>> }
>>>>
>>>> (Any issues regarding anonymous unions/structs are left as an exercise
>>>> for the reader :-)
>>>
>>> This might work in C, but a problem is that the C++ standard says:
>>>
>>> 9.3 Unions
>>> "In a union, a non-static data member is active if its name refers to
>>> an object whose lifetime has begun and has not ended (3.8). At most
>>> one of the non-static data members of an object of union type can be
>>> active at any time, that is, the value of at most one of the
>>> non-static data members can be stored in a union at any time. "
>>>
>>> So, if the struct with a, b, c, and d is active, as_array is not
>>> "stored" and cannot be read. You can't read an object that isn't
>>> there!
>>
>> So this is another way that C++ is not upwards compatible from
>> C?
>
> In theory, yes. But the platforms that support C++ are much more
> "normal" than those that support C, and there are far fewer C++
> compilers around. If all these C++ compilers support type punning
> through unions, as gcc and clang do, then there will be no
> incompatibility in practice.
IMO it is unacceptably bad practice to write code that depends
on this sort of untestable guarantee.
> And perhaps someday someone will tidy up such missing points from the
> C++ standards so that they catch up with the changes in later C
> standards.
At least in this area it looks like the departure is deliberate
and getting wider with time, not narrower.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-02 09:24 +0200 |
| Message-ID | <nqb9ev$at9$1@dont-email.me> |
| In reply to | #44717 |
On 02/09/16 03:08, Tim Rentsch wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 01/09/16 18:03, Tim Rentsch wrote:
>>> Bo Persson <bop@gmb.dk> writes:
>>>
>>>> On 2016-08-31 15:20, David Brown wrote:
>>>>> On 31/08/16 14:59, Melzzzzz wrote:
>>>>>> Code in question is like this:
>>>>>>
>>>>>> struct Problem{
>>>>>> uint32_t a;
>>>>>> uint32_t b;
>>>>>> uint64_t c;
>>>>>> uint32_t d;
>>>>>> bool check_it() {
>>>>>> for (uint32_t* i = &a;i != &d; ++i)
>>>>>> if (*i>0) return true;
>>>>>> return false;
>>>>>> }
>>>>>>
>>>>>> };
>>>>>>
>>>>>> I am not sure if this will work, so if someone has clear explanation
>>>>>> why it will work (or not) , I would be grateful.
>>>>>
>>>>> I don't think you are guaranteed that a, b, c, and d follow each other
>>>>> in the structure layout (though it is very likely to be the case). With
>>>>> a pointer to a single item &a, incrementing the pointer is undefined
>>>>> behaviour - as is accessing *i. And accessing the uint64_t member using
>>>>> an uint32_t* pointer contradicts aliasing restrictions.
>>>>>
>>>>> All in all, the compiler is free to assume that this code is full of
>>>>> undefined behaviour, therefore you don't really care what it does -
>>>>> therefore it can all be optimised to "return true", "return false", or
>>>>> even "launch nasal daemons". (This last option is legal for the
>>>>> compiler, but thankfully unlikely in practice.)
>>>>>
>>>>> You can make it legal with:
>>>>>
>>>>> struct Problem {
>>>>> union {
>>>>> struct {
>>>>> uint32_t a;
>>>>> uint32_t b;
>>>>> uint64_t c;
>>>>> uint32_t d;
>>>>> }
>>>>> uint32_t as_array[5];
>>>>> }
>>>>> bool check_it() {
>>>>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>>>>> if (*i > 0) return true;
>>>>> return false;
>>>>> }
>>>>> }
>>>>>
>>>>> (Any issues regarding anonymous unions/structs are left as an exercise
>>>>> for the reader :-)
>>>>
>>>> This might work in C, but a problem is that the C++ standard says:
>>>>
>>>> 9.3 Unions
>>>> "In a union, a non-static data member is active if its name refers to
>>>> an object whose lifetime has begun and has not ended (3.8). At most
>>>> one of the non-static data members of an object of union type can be
>>>> active at any time, that is, the value of at most one of the
>>>> non-static data members can be stored in a union at any time. "
>>>>
>>>> So, if the struct with a, b, c, and d is active, as_array is not
>>>> "stored" and cannot be read. You can't read an object that isn't
>>>> there!
>>>
>>> So this is another way that C++ is not upwards compatible from
>>> C?
>>
>> In theory, yes. But the platforms that support C++ are much more
>> "normal" than those that support C, and there are far fewer C++
>> compilers around. If all these C++ compilers support type punning
>> through unions, as gcc and clang do, then there will be no
>> incompatibility in practice.
>
> IMO it is unacceptably bad practice to write code that depends
> on this sort of untestable guarantee.
That is certainly true for some types of code. But a great deal of code
does not need wide portability. If I am writing code that will run on a
particular target, compiled with a particular toolchain, it is bad
practice to write widely portable code if knowledge of the target and
toolchain could mean cleaner, clearer, safer and more efficient code.
Assumptions should be well documented, preferably with compile-time
checking, but it is perfectly acceptable to rely on implementation
defined behaviour. If I am writing a driver for the ADC on a
microcontroller, I refuse to write some memcpy monstrosity just in case
someone wants to compile the code on a PDP-9. And if gcc extensions let
me make the code better, then I will use gcc extensions - and you can't
use the same code with Keil or IAR's compilers.
But of course this sort of thing will vary depending on the type of
programming you do. /I/ can work this way. When I put together a
project, the toolchain (compiler, linker scripts, libraries, etc.) is
part of the project, and archived with it. I can pull up 20 year old
projects, do a clean make, and get bit-identical binary outputs (yes,
I've done that).
However, if you are writing some library functions that may be used on
many different systems - including those in the future - then you have
very different requirements and restrictions in the way you code.
>
>> And perhaps someday someone will tidy up such missing points from the
>> C++ standards so that they catch up with the changes in later C
>> standards.
>
> At least in this area it looks like the departure is deliberate
> and getting wider with time, not narrower.
>
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2016-09-04 06:31 -0700 |
| Message-ID | <kfnd1kjokox.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #44725 |
David Brown <david.brown@hesbynett.no> writes:
> On 02/09/16 03:08, Tim Rentsch wrote:
>> David Brown <david.brown@hesbynett.no> writes:
>>
>>> On 01/09/16 18:03, Tim Rentsch wrote:
>>>> Bo Persson <bop@gmb.dk> writes:
>>>>
>>>>> On 2016-08-31 15:20, David Brown wrote:
>>>>>> On 31/08/16 14:59, Melzzzzz wrote:
>>>>>>> Code in question is like this:
>>>>>>>
>>>>>>> struct Problem{
>>>>>>> uint32_t a;
>>>>>>> uint32_t b;
>>>>>>> uint64_t c;
>>>>>>> uint32_t d;
>>>>>>> bool check_it() {
>>>>>>> for (uint32_t* i = &a;i != &d; ++i)
>>>>>>> if (*i>0) return true;
>>>>>>> return false;
>>>>>>> }
>>>>>>>
>>>>>>> };
>>>>>>>
>>>>>>> I am not sure if this will work, so if someone has clear explanation
>>>>>>> why it will work (or not) , I would be grateful.
>>>>>>
>>>>>> I don't think you are guaranteed that a, b, c, and d follow each other
>>>>>> in the structure layout (though it is very likely to be the case). With
>>>>>> a pointer to a single item &a, incrementing the pointer is undefined
>>>>>> behaviour - as is accessing *i. And accessing the uint64_t member using
>>>>>> an uint32_t* pointer contradicts aliasing restrictions.
>>>>>>
>>>>>> All in all, the compiler is free to assume that this code is full of
>>>>>> undefined behaviour, therefore you don't really care what it does -
>>>>>> therefore it can all be optimised to "return true", "return false", or
>>>>>> even "launch nasal daemons". (This last option is legal for the
>>>>>> compiler, but thankfully unlikely in practice.)
>>>>>>
>>>>>> You can make it legal with:
>>>>>>
>>>>>> struct Problem {
>>>>>> union {
>>>>>> struct {
>>>>>> uint32_t a;
>>>>>> uint32_t b;
>>>>>> uint64_t c;
>>>>>> uint32_t d;
>>>>>> }
>>>>>> uint32_t as_array[5];
>>>>>> }
>>>>>> bool check_it() {
>>>>>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>>>>>> if (*i > 0) return true;
>>>>>> return false;
>>>>>> }
>>>>>> }
>>>>>>
>>>>>> (Any issues regarding anonymous unions/structs are left as an exercise
>>>>>> for the reader :-)
>>>>>
>>>>> This might work in C, but a problem is that the C++ standard says:
>>>>>
>>>>> 9.3 Unions
>>>>> "In a union, a non-static data member is active if its name refers to
>>>>> an object whose lifetime has begun and has not ended (3.8). At most
>>>>> one of the non-static data members of an object of union type can be
>>>>> active at any time, that is, the value of at most one of the
>>>>> non-static data members can be stored in a union at any time. "
>>>>>
>>>>> So, if the struct with a, b, c, and d is active, as_array is not
>>>>> "stored" and cannot be read. You can't read an object that isn't
>>>>> there!
>>>>
>>>> So this is another way that C++ is not upwards compatible from
>>>> C?
>>>
>>> In theory, yes. But the platforms that support C++ are much more
>>> "normal" than those that support C, and there are far fewer C++
>>> compilers around. If all these C++ compilers support type punning
>>> through unions, as gcc and clang do, then there will be no
>>> incompatibility in practice.
>>
>> IMO it is unacceptably bad practice to write code that depends
>> on this sort of untestable guarantee.
>
> That is certainly true for some types of code. But a great deal of code
> does not need wide portability. [...]
I'm afraid you misunderstood my point, which has nothing to
do with running on multiple platforms.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-04 20:19 +0200 |
| Message-ID | <nqhoj0$se9$1@dont-email.me> |
| In reply to | #44811 |
On 04/09/16 15:31, Tim Rentsch wrote:
> David Brown <david.brown@hesbynett.no> writes:
>
>> On 02/09/16 03:08, Tim Rentsch wrote:
>>> David Brown <david.brown@hesbynett.no> writes:
>>>
>>>> On 01/09/16 18:03, Tim Rentsch wrote:
>>>>> Bo Persson <bop@gmb.dk> writes:
>>>>>
>>>>>> On 2016-08-31 15:20, David Brown wrote:
>>>>>>> On 31/08/16 14:59, Melzzzzz wrote:
>>>>>>>> Code in question is like this:
>>>>>>>>
>>>>>>>> struct Problem{
>>>>>>>> uint32_t a;
>>>>>>>> uint32_t b;
>>>>>>>> uint64_t c;
>>>>>>>> uint32_t d;
>>>>>>>> bool check_it() {
>>>>>>>> for (uint32_t* i = &a;i != &d; ++i)
>>>>>>>> if (*i>0) return true;
>>>>>>>> return false;
>>>>>>>> }
>>>>>>>>
>>>>>>>> };
>>>>>>>>
>>>>>>>> I am not sure if this will work, so if someone has clear explanation
>>>>>>>> why it will work (or not) , I would be grateful.
>>>>>>>
>>>>>>> I don't think you are guaranteed that a, b, c, and d follow each other
>>>>>>> in the structure layout (though it is very likely to be the case). With
>>>>>>> a pointer to a single item &a, incrementing the pointer is undefined
>>>>>>> behaviour - as is accessing *i. And accessing the uint64_t member using
>>>>>>> an uint32_t* pointer contradicts aliasing restrictions.
>>>>>>>
>>>>>>> All in all, the compiler is free to assume that this code is full of
>>>>>>> undefined behaviour, therefore you don't really care what it does -
>>>>>>> therefore it can all be optimised to "return true", "return false", or
>>>>>>> even "launch nasal daemons". (This last option is legal for the
>>>>>>> compiler, but thankfully unlikely in practice.)
>>>>>>>
>>>>>>> You can make it legal with:
>>>>>>>
>>>>>>> struct Problem {
>>>>>>> union {
>>>>>>> struct {
>>>>>>> uint32_t a;
>>>>>>> uint32_t b;
>>>>>>> uint64_t c;
>>>>>>> uint32_t d;
>>>>>>> }
>>>>>>> uint32_t as_array[5];
>>>>>>> }
>>>>>>> bool check_it() {
>>>>>>> for (uint32_t* i = &as_array[0]; i != &as_array[4]; ++i)
>>>>>>> if (*i > 0) return true;
>>>>>>> return false;
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> (Any issues regarding anonymous unions/structs are left as an exercise
>>>>>>> for the reader :-)
>>>>>>
>>>>>> This might work in C, but a problem is that the C++ standard says:
>>>>>>
>>>>>> 9.3 Unions
>>>>>> "In a union, a non-static data member is active if its name refers to
>>>>>> an object whose lifetime has begun and has not ended (3.8). At most
>>>>>> one of the non-static data members of an object of union type can be
>>>>>> active at any time, that is, the value of at most one of the
>>>>>> non-static data members can be stored in a union at any time. "
>>>>>>
>>>>>> So, if the struct with a, b, c, and d is active, as_array is not
>>>>>> "stored" and cannot be read. You can't read an object that isn't
>>>>>> there!
>>>>>
>>>>> So this is another way that C++ is not upwards compatible from
>>>>> C?
>>>>
>>>> In theory, yes. But the platforms that support C++ are much more
>>>> "normal" than those that support C, and there are far fewer C++
>>>> compilers around. If all these C++ compilers support type punning
>>>> through unions, as gcc and clang do, then there will be no
>>>> incompatibility in practice.
>>>
>>> IMO it is unacceptably bad practice to write code that depends
>>> on this sort of untestable guarantee.
>>
>> That is certainly true for some types of code. But a great deal of code
>> does not need wide portability. [...]
>
> I'm afraid you misunderstood my point, which has nothing to
> do with running on multiple platforms.
>
So you are happy that some code is implementation-dependent, and if the
implementation documents a given behaviour it is okay to rely on it?
But if code is supposed to be portable (either across different current
toolchains, or to unknown future ones), then you can't rely on it. And
if the implementation seems to work for the given code, but does not
documentation a guarantee, then it may be a very risky thing to rely on
it - but it may be acceptable in certain circumstances.
What am I missing, or misunderstanding here?
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2016-08-31 15:45 +0200 |
| Message-ID | <nq6n13$1qdi$1@gioia.aioe.org> |
| In reply to | #44630 |
On 8/31/2016 2:59 PM, Melzzzzz wrote:
> Code in question is like this:
>
> struct Problem{
> uint32_t a;
> uint32_t b;
> uint64_t c;
> uint32_t d;
> bool check_it() {
> for (uint32_t* i = &a;i != &d; ++i)
> if (*i>0) return true;
> return false;
> }
>
> };
>
> I am not sure if this will work, so if someone has clear explanation
> why it will work (or not) , I would be grateful.
>
You need to specify __attribute__((__packed__)) for a, b, c, d (esp. d)
Moreover, the guaranteed ordering of a, b, c, d needs to be verified
with the standard:
iso 9.2.13 (draft 2014-11-19):
"Nonstatic data members of a (non-union) class with the same access
control (Clause 11) are allocated so that later members have higher
addresses within a class object. The order of allocation of non-static
data members with different access control is unspecified (Clause 11).
Implementation alignment requirements might cause two adjacent members
not to be allocated immediately after each other; so might requirements
for space for managing virtual functions (10.3) and virtual base classes
(10.1)."
Obviously the test may only work for comparison with 0.
I would not classify this practice as good, in the sense that I would
not do this in production code.
Best Regards,
M.
[toc] | [prev] | [next] | [standalone]
| From | Melzzzzz <mel@zzzzz.com> |
|---|---|
| Date | 2016-08-31 15:59 +0200 |
| Message-ID | <20160831155955.418179d7@maxa-pc> |
| In reply to | #44632 |
On Wed, 31 Aug 2016 15:45:07 +0200
Manfred <noname@invalid.add> wrote:
> On 8/31/2016 2:59 PM, Melzzzzz wrote:
> > Code in question is like this:
> >
> > struct Problem{
> > uint32_t a;
> > uint32_t b;
> > uint64_t c;
> > uint32_t d;
> > bool check_it() {
> > for (uint32_t* i = &a;i != &d; ++i)
> > if (*i>0) return true;
> > return false;
> > }
> >
> > };
> >
> > I am not sure if this will work, so if someone has clear explanation
> > why it will work (or not) , I would be grateful.
> >
>
> You need to specify __attribute__((__packed__)) for a, b, c, d (esp.
> d)
Oh I forgot to say that that attribute is specified.
Moreover, the guaranteed ordering of a, b, c, d needs to be
> verified with the standard:
> iso 9.2.13 (draft 2014-11-19):
> "Nonstatic data members of a (non-union) class with the same access
> control (Clause 11) are allocated so that later members have higher
> addresses within a class object. The order of allocation of
> non-static data members with different access control is unspecified
> (Clause 11). Implementation alignment requirements might cause two
> adjacent members not to be allocated immediately after each other; so
> might requirements for space for managing virtual functions (10.3)
> and virtual base classes (10.1)."
>
> Obviously the test may only work for comparison with 0.
> I would not classify this practice as good, in the sense that I would
> not do this in production code.
I agree.
>
> Best Regards,
> M.
>
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-08-31 16:22 +0200 |
| Message-ID | <nq6p82$ijc$1@dont-email.me> |
| In reply to | #44632 |
On 31/08/16 15:45, Manfred wrote:
> On 8/31/2016 2:59 PM, Melzzzzz wrote:
>> Code in question is like this:
>>
>> struct Problem{
>> uint32_t a;
>> uint32_t b;
>> uint64_t c;
>> uint32_t d;
>> bool check_it() {
>> for (uint32_t* i = &a;i != &d; ++i)
>> if (*i>0) return true;
>> return false;
>> }
>>
>> };
>>
>> I am not sure if this will work, so if someone has clear explanation
>> why it will work (or not) , I would be grateful.
>>
>
> You need to specify __attribute__((__packed__)) for a, b, c, d (esp. d)
> Moreover, the guaranteed ordering of a, b, c, d needs to be verified
> with the standard:
> iso 9.2.13 (draft 2014-11-19):
> "Nonstatic data members of a (non-union) class with the same access
> control (Clause 11) are allocated so that later members have higher
> addresses within a class object. The order of allocation of non-static
> data members with different access control is unspecified (Clause 11).
> Implementation alignment requirements might cause two adjacent members
> not to be allocated immediately after each other; so might requirements
> for space for managing virtual functions (10.3) and virtual base classes
> (10.1)."
And note that at least one major compiler - gcc - /did/ re-organise the
ordering in structs when appropriate optimisation flags were enabled.
It would not do so if you took addresses like this, and the optimisation
has been removed in later versions of gcc (because it played badly with
link-time optimisation), but compilers might make such re-organisations
in the future.
Of course, individual implementations might guarantee that this works,
even though the standards don't.
>
> Obviously the test may only work for comparison with 0.
> I would not classify this practice as good, in the sense that I would
> not do this in production code.
>
> Best Regards,
> M.
>
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2016-08-31 17:06 +0200 |
| Message-ID | <nq6rp7$3ip$1@gioia.aioe.org> |
| In reply to | #44637 |
On 8/31/2016 4:22 PM, David Brown wrote: >> Moreover, the guaranteed ordering of a, b, c, d needs to be verified >> with the standard: >> iso 9.2.13 (draft 2014-11-19): >> "Nonstatic data members of a (non-union) class with the same access >> control (Clause 11) are allocated so that later members have higher >> addresses within a class object. The order of allocation of non-static >> data members with different access control is unspecified (Clause 11). >> Implementation alignment requirements might cause two adjacent members >> not to be allocated immediately after each other; so might requirements >> for space for managing virtual functions (10.3) and virtual base classes >> (10.1)." > > And note that at least one major compiler - gcc - /did/ re-organise the > ordering in structs when appropriate optimisation flags were enabled. > It would not do so if you took addresses like this, and the optimisation > has been removed in later versions of gcc (because it played badly with > link-time optimisation), but compilers might make such re-organisations > in the future. > > Of course, individual implementations might guarantee that this works, > even though the standards don't. > Data members ordering is guaranteed by the standard, but objections still hold in that, besides packing issues, the same standard in principle allows for: - interleaving of data members with different access control, so that a private member may fall in between a bunch of public ones. - "space for managing virtual functions and virtual base classes" to fall anywhere. Maybe your proposal of union+array could prevent this?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-08-31 19:29 +0200 |
| Message-ID | <nq746l$r3b$1@dont-email.me> |
| In reply to | #44638 |
On 31/08/16 17:06, Manfred wrote:
> On 8/31/2016 4:22 PM, David Brown wrote:
>>> Moreover, the guaranteed ordering of a, b, c, d needs to be verified
>>> with the standard:
>>> iso 9.2.13 (draft 2014-11-19):
>>> "Nonstatic data members of a (non-union) class with the same access
>>> control (Clause 11) are allocated so that later members have higher
>>> addresses within a class object. The order of allocation of non-static
>>> data members with different access control is unspecified (Clause 11).
>>> Implementation alignment requirements might cause two adjacent members
>>> not to be allocated immediately after each other; so might requirements
>>> for space for managing virtual functions (10.3) and virtual base classes
>>> (10.1)."
>>
>> And note that at least one major compiler - gcc - /did/ re-organise the
>> ordering in structs when appropriate optimisation flags were enabled.
>> It would not do so if you took addresses like this, and the optimisation
>> has been removed in later versions of gcc (because it played badly with
>> link-time optimisation), but compilers might make such re-organisations
>> in the future.
>>
>> Of course, individual implementations might guarantee that this works,
>> even though the standards don't.
>>
> Data members ordering is guaranteed by the standard, but objections
> still hold in that, besides packing issues, the same standard in
> principle allows for:
> - interleaving of data members with different access control, so that a
> private member may fall in between a bunch of public ones.
> - "space for managing virtual functions and virtual base classes" to
> fall anywhere.
> Maybe your proposal of union+array could prevent this?
>
Apparently, you are not allowed to access the different parts of the
union as I had thought. My knowledge of such details in C++ is a good
deal less than my knowledge of C, and my knowledge of C has holes too!
However, the standard does not guarantee that data members are ordered
in the same way as they are declared in the struct - it guarantees that
they /appear/ that way to any code with defined behaviour. If code does
not do anything that might be influenced by the ordering, or the code
that is dependent on the order has undefined behaviour (as in this
case), then the compiler /can/ re-order the data members. This is all
part of the "as if" rule - compilers can generate anything they want, as
long as the code runs "as if" it followed the abstract machine and C or
C++ rules directly.
So if you have a struct, and use things like the "offsetof" macro on its
fields, the compiler is going to have to allocate members in the
specified order. But if you have a "struct { int a; int b; }" used as a
local variable without ever referring to their addresses, not only can
the compiler swap a and b, but it can put them in registers, or even
omit one of the members altogether if it can be "optimised away".
[toc] | [prev] | [next] | [standalone]
| From | Chris Vine <chris@cvine--nospam--.freeserve.co.uk> |
|---|---|
| Date | 2016-08-31 21:52 +0100 |
| Message-ID | <20160831215212.63b20ea7@bother.homenet> |
| In reply to | #44640 |
On Wed, 31 Aug 2016 19:29:57 +0200 David Brown <david.brown@hesbynett.no> wrote: [snip] > Apparently, you are not allowed to access the different parts of the > union as I had thought. My knowledge of such details in C++ is a > good deal less than my knowledge of C, and my knowledge of C has > holes too! It has undefined behaviour in C89, and C99 as originally printed. It has defined behaviour in C99 with Technical Corrigendum 3 applied and in C11, except that if there are padding bytes they can have a trap representation (§6.2.6.1/6 and /7 of C11 read with footnote 95 of §6.5.2.3/3 if you want the reference). The latter (trap representations) can be ignored on any architecture running C++. GCC and clang permit type punning through unions in C++ in the same way as an extension. To make it portable I guess you could put the code in a separate translation unit compiled as C11 and link to that in your C++ code. It seems a bit overly complicated though. Chris
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2016-09-01 09:07 +0200 |
| Message-ID | <nq8k3g$51b$1@dont-email.me> |
| In reply to | #44644 |
On 31/08/16 22:52, Chris Vine wrote: > On Wed, 31 Aug 2016 19:29:57 +0200 > David Brown <david.brown@hesbynett.no> wrote: > [snip] >> Apparently, you are not allowed to access the different parts of the >> union as I had thought. My knowledge of such details in C++ is a >> good deal less than my knowledge of C, and my knowledge of C has >> holes too! > > It has undefined behaviour in C89, and C99 as originally printed. It > has defined behaviour in C99 with Technical Corrigendum 3 applied and in > C11, except that if there are padding bytes they can have a trap > representation (§6.2.6.1/6 and /7 of C11 read with footnote 95 of > §6.5.2.3/3 if you want the reference). Yes, that's how I remember the standards. C90 standards did not allow this sort of access to different parts of the union, but most implementations did - and programmers relied on that as a way of changing types without changing the underlying representation. So the C99 (after the TC's) standard put it in. But I guess C++ gets most of its C stuff from C90. > The latter (trap > representations) can be ignored on any architecture running C++. Is that guaranteed by the C++ standards, or is it just that no one has made a C++ compiler for one of the weird architectures that has trap representations? (In this particular case, the types in question were uint32_t and uint64_t - these cannot have trap representations in C. But pointers, signed integers, and floating point types could have trap representations, in theory.) > GCC > and clang permit type punning through unions in C++ in the same way as > an extension. I believe the OP was using one of these (since he uses __attribute__). > > To make it portable I guess you could put the code in a separate > translation unit compiled as C11 and link to that in your C++ code. It > seems a bit overly complicated though. > Indeed. Sometimes it makes sense to use implementation-specific behaviour (like "it works with gcc and clang"). But that's up to the OP and his requirements. > Chris >
[toc] | [prev] | [next] | [standalone]
| From | Chris Vine <chris@cvine--nospam--.freeserve.co.uk> |
|---|---|
| Date | 2016-09-01 12:30 +0100 |
| Message-ID | <20160901123037.3255928f@bother.homenet> |
| In reply to | #44652 |
On Thu, 01 Sep 2016 09:07:27 +0200 David Brown <david.brown@hesbynett.no> wrote: > On 31/08/16 22:52, Chris Vine wrote: > > On Wed, 31 Aug 2016 19:29:57 +0200 > > David Brown <david.brown@hesbynett.no> wrote: > > [snip] > >> Apparently, you are not allowed to access the different parts of > >> the union as I had thought. My knowledge of such details in C++ > >> is a good deal less than my knowledge of C, and my knowledge of C > >> has holes too! > > > > It has undefined behaviour in C89, and C99 as originally printed. > > It has defined behaviour in C99 with Technical Corrigendum 3 > > applied and in C11, except that if there are padding bytes they can > > have a trap representation (§6.2.6.1/6 and /7 of C11 read with > > footnote 95 of §6.5.2.3/3 if you want the reference). > > Yes, that's how I remember the standards. C90 standards did not allow > this sort of access to different parts of the union, but most > implementations did - and programmers relied on that as a way of > changing types without changing the underlying representation. So the > C99 (after the TC's) standard put it in. > > But I guess C++ gets most of its C stuff from C90. > > > The latter (trap > > representations) can be ignored on any architecture running C++. > > Is that guaranteed by the C++ standards, or is it just that no one has > made a C++ compiler for one of the weird architectures that has trap > representations? > > (In this particular case, the types in question were uint32_t and > uint64_t - these cannot have trap representations in C. But pointers, > signed integers, and floating point types could have trap > representations, in theory.) A trap representation is (according to C) "an object representation that need not represent a value of the object type". §6.2.6.1/5 goes on to say that "Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined. Such a representation is called a trap representation". The resulting undefined behaviour may include the triggering of hardware traps. C++ has not yet imported the "trap representation" from C: C++ instead refers to uninitialised values of trivial types having "an indeterminate value". In particular it does not so far permit access to indeterminate values via the character types, but by the same token I do not think that any architecture running C++ has hardware-level traps for invalid signed arithmetic or floating points or for copying invalid pointer values (but see below on pointers). §8.5/12 of the draft C++17 standard sort-of introduces something similar to the rules on trap representations by stating (in a convoluted fashion) that if you evaluate an indeterminate value except via a narrow unsigned character type you have undefined behaviour. Since "evaluate" includes copy, this seems inconsistent with the welcome licence given by §3.7.4.2/4 of C++14/17 which makes copying a pointer value which is neither the null pointer nor the address of a valid object implementation-defined behaviour instead of undefined behaviour (C++14 tips it hat to C hardware traps by indicating that that implementation-defined behaviour may include having "a system-generated runtime fault"). No one yet seems to have spotted this inconsistency. Chris
[toc] | [prev] | [next] | [standalone]
Page 1 of 7 [1] 2 3 4 5 6 7 Next page →
Back to top | Article view | comp.lang.c++
csiph-web