title: Is it UB to access a member by casting an object pointer to `char *`, then doing `*(member_type*)(pointer + offset)`?
body: <p>Here's an example:</p>
  
  <pre><code>#include &lt;cstddef&gt;
  #include &lt;iostream&gt;
  
  struct A
  {
      char padding[7];
      int x;
  };
  constexpr int offset = offsetof(A, x);
  
  int main()
  {
      A a;
      a.x = 42;
      char *ptr = (char *)&amp;a;
      std::cout &lt;&lt; *(int *)(ptr + offset) &lt;&lt; '\n'; // Well-defined or not?
  }
  </code></pre>
  
  <p>I always assumed that it's well-defined (otherwise what would be the point of <code>offsetof</code>), but wasn't sure.</p>
  
  <p>Recently I <a href="https://stackoverflow.com/questions/62328001/is-there-a-way-to-loop-over-different-data-members-of-an-object-in-c/62328138?noredirect=1#comment110233955_62328138">was told</a> that it's in fact UB, so I want to figure it out once and for all.</p>
  
  <p>Does the example above cause UB or not? If you modify the class to not be standard-layout, does it affect the result?</p>
  
  <p>And if it's UB, are there any workarounds for it (e.g. applying <code>std::launder</code>)?</p>
  
  <hr>
  
  <p>This entire topic seems to be moot and underspecified.</p>
  
  <p>Here's some information I was able to find:</p>
  
  <ul>
  <li><p><a href="https://stackoverflow.com/a/55578221/2752075">Is adding to a “char *” pointer UB, when it doesn't actually point to a char array?</a> - In 2011, CWG confirmed that we're allowed to examine the representation of a standard-layout object through an <code>unsigned char</code> pointer.</p>
  
  <ul>
  <li>Unclear if a <code>char</code> pointer can be used insteaed, common sense says it can.</li>
  <li><p>Unclear if staring from C++17 <code>std::launder</code> needs to be applied to the result of the <code>(unsigned char *)</code> cast. Given that it would be a breaking change, it's probably unnecessarly, at least in practice.</p></li>
  <li><p>Unclear why C++17 changed <code>offsetof</code> to conditionally-support non-standard-layout types (used to be UB). It seems to imply that if an implementation supports that, then it also lets you examine the representation of non-standard-layout objects through <code>unsigned char *</code>.</p></li>
  </ul></li>
  <li><p><a href="https://stackoverflow.com/questions/55578429/do-we-need-to-use-stdlaunder-when-doing-pointer-arithmetic-within-a-standard-l">Do we need to use std::launder when doing pointer arithmetic within a standard-layout object (e.g., with offsetof)?</a> - A question similar to this one. No definitive answer was given.</p></li>
  </ul>