Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #44630 > unrolled thread

This will work or not?

Started byMelzzzzz <mel@zzzzz.com>
First post2016-08-31 14:59 +0200
Last post2016-09-05 21:25 +0100
Articles 20 on this page of 123 — 25 participants

Back to article view | Back to comp.lang.c++


Contents

  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 →


#44630 — This will work or not?

FromMelzzzzz <mel@zzzzz.com>
Date2016-08-31 14:59 +0200
SubjectThis 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]


#44631

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44634

Frommark <mark@invalid.invalid>
Date2016-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]


#44635

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44636

Fromscott@slp53.sl.home (Scott Lurndal)
Date2016-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]


#44639

FromBo Persson <bop@gmb.dk>
Date2016-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]


#44684

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-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]


#44706

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44717

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-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]


#44725

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44811

FromTim Rentsch <txr@alumni.caltech.edu>
Date2016-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]


#44832

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44632

FromManfred <noname@invalid.add>
Date2016-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]


#44633

FromMelzzzzz <mel@zzzzz.com>
Date2016-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]


#44637

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44638

FromManfred <noname@invalid.add>
Date2016-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]


#44640

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44644

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2016-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]


#44652

FromDavid Brown <david.brown@hesbynett.no>
Date2016-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]


#44664

FromChris Vine <chris@cvine--nospam--.freeserve.co.uk>
Date2016-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