<div dir="ltr">I posted this to std-discussion, but I figured I might get more response from the undefined-behavior list instead.<br><div><br><br>The C++ Standard permits you to use <span style="font-family:monospace,monospace">offsetof()</span> on standard-layout
classes, but does it permit using that offset in pointer arithmetic with
object pointers that have been <span style="font-family:monospace,monospace">reinterpret_cast</span> to [<span style="font-family:monospace,monospace">unsigned</span>] <span style="font-family:monospace,monospace">char *</span>?<br><br>The
section on pointer arithmetic is predicated on "if the pointer object
points to an element of an array object" (§5.7/4), with undefined
behavior otherwise. It has a footnote stating that, "an object that is
not an array is considered to belong to a single-element array for this
purpose". But if you <span style="font-family:monospace,monospace">reinterpret_cast</span> a pointer to a single object into
a <span style="font-family:monospace,monospace">char</span> pointer, that's not a pointer to an array object.<br><br>Does
this mean that doing pointer arithmetic on a <span style="font-family:monospace,monospace">reinterpret_cast</span> <span style="font-family:monospace,monospace">char</span>
pointer of a single object in order to reach other members is undefined
behavior even for standard-layout types? It seems to me that this was
not the intention of the Standard. Getting around this would require
using <span style="font-family:monospace,monospace">memcpy</span> into a <span style="font-family:monospace,monospace">char</span> array, only ever using the offset for indexing
into that <span style="font-family:monospace,monospace">char</span> array, then copying back.<br><br>Another possible
interpretation of the Standard is that the <span style="font-family:monospace,monospace">reinterpret_cast</span> pointer
*does* point to an array. One way this interpretation could be derived
is from §1.8/5: "An object of trivially copyable or standard-layout type
(3.9) shall occupy contiguous bytes of storage.".<br><br><br><div style="background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px;word-wrap:break-word"><code><div><span style="color:rgb(136,0,0)">#include</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)"><cmath></span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(136,0,0)">#include</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)"><cstdio></span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(136,0,0)">#include</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)"><cstdlib></span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(136,0,0)">#include</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)"><cstring></span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(136,0,0)">#include</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)"><type_traits></span><span style="color:rgb(0,0,0)"><br><br></span><span style="color:rgb(0,0,136)">struct</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(102,0,102)">Meow</span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(102,102,0)">{</span><span style="color:rgb(0,0,0)"><br> </span><span style="color:rgb(0,0,136)">int</span><span style="color:rgb(0,0,0)"> x</span><span style="color:rgb(102,102,0)">;</span><span style="color:rgb(0,0,0)"><br> </span><span style="color:rgb(0,0,136)">float</span><span style="color:rgb(0,0,0)"> y</span><span style="color:rgb(102,102,0)">;</span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(102,102,0)">};</span><span style="color:rgb(0,0,0)"><br><br></span><span style="color:rgb(0,0,136)">int</span><span style="color:rgb(0,0,0)"> main</span><span style="color:rgb(102,102,0)">()</span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(102,102,0)">{</span><span style="color:rgb(0,0,0)"><br> </span><span style="color:rgb(102,0,102)">Meow</span><span style="color:rgb(0,0,0)"> meow</span><span style="color:rgb(102,102,0)">;</span><span style="color:rgb(0,0,0)"><br> </span><span style="color:rgb(0,0,136)">static_assert</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(0,0,0)">std</span><span style="color:rgb(102,102,0)">::</span><span style="color:rgb(0,0,0)">is_standard_layout</span><span style="color:rgb(102,102,0)"><</span><span style="color:rgb(102,0,102)">Meow</span><span style="color:rgb(102,102,0)">>::</span><span style="color:rgb(0,0,0)">value</span><span style="color:rgb(102,102,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,136,0)">"Meow isn't standard-layout"</span><span style="color:rgb(102,102,0)">);</span><span style="color:rgb(0,0,0)"><br><br> </span><span style="color:rgb(136,0,0)">// Aliasing rules allow this (3.10/8)</span><span style="color:rgb(0,0,0)"><br> </span><span style="color:rgb(0,0,136)">unsigned</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,136)">char</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(102,102,0)">*</span><span style="color:rgb(0,0,0)">p </span><span style="color:rgb(102,102,0)">=</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,136)">reinterpret_cast</span><span style="color:rgb(102,102,0)"><</span><span style="color:rgb(0,0,136)">unsigned</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,136)">char</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(102,102,0)">*>(&</span><span style="color:rgb(0,0,0)">meow</span><span style="color:rgb(102,102,0)">);</span><span style="color:rgb(0,0,0)"><br><br> </span><span style="color:rgb(136,0,0)">// Meow is standard-layout, but is this technically undefined behavior?</span><span style="color:rgb(0,0,0)"><br> p </span><span style="color:rgb(102,102,0)">+=</span><span style="color:rgb(0,0,0)"> offsetof</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(102,0,102)">Meow</span><span style="color:rgb(102,102,0)">,</span><span style="color:rgb(0,0,0)"> y</span><span style="color:rgb(102,102,0)">);</span><span style="color:rgb(0,0,0)"><br><br> </span><span style="color:rgb(0,0,136)">float</span><span style="color:rgb(0,0,0)"> z </span><span style="color:rgb(102,102,0)">=</span><span style="color:rgb(0,0,0)"> std</span><span style="color:rgb(102,102,0)">::</span><span style="color:rgb(0,0,0)">exp</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(0,102,102)">1.0f</span><span style="color:rgb(102,102,0)">);</span><span style="color:rgb(0,0,0)"><br> std</span><span style="color:rgb(102,102,0)">::</span><span style="color:rgb(0,0,0)">memcpy</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(0,0,0)">p</span><span style="color:rgb(102,102,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(102,102,0)">&</span><span style="color:rgb(0,0,0)">z</span><span style="color:rgb(102,102,0)">,</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,136)">sizeof</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(0,0,136)">float</span><span style="color:rgb(102,102,0)">));</span><span style="color:rgb(0,0,0)"><br> <br> std</span><span style="color:rgb(102,102,0)">::</span><span style="color:rgb(0,0,0)">printf</span><span style="color:rgb(102,102,0)">(</span><span style="color:rgb(0,136,0)">"%f\n"</span><span style="color:rgb(102,102,0)">,</span><span style="color:rgb(0,0,0)"> meow</span><span style="color:rgb(102,102,0)">.</span><span style="color:rgb(0,0,0)">y</span><span style="color:rgb(102,102,0)">);</span><span style="color:rgb(0,0,0)"><br><br> </span><span style="color:rgb(0,0,136)">return</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,102,102)">0</span><span style="color:rgb(102,102,0)">;</span><span style="color:rgb(0,0,0)"><br></span><span style="color:rgb(102,102,0)">}</span><span style="color:rgb(0,0,0)"><br></span></div></code></div><br></div><div><br></div><div>Addendum to my original email: For this to be undefined would be to invalidate decades of existing programming practice.<br></div><div><br></div><div>Melissa<br></div></div>