title: Is this a violation of the strict aliasing rule?
body: <p>Consider this C code:</p>
  
  <pre><code>extern void CheckIfPtrInHeap( void* p );
  
  void TakePtr( void** p, size_t n )
  {
    for( size_t i = 0 ; i &lt; n ; ++i )
      CheckIfPtrInHeap( p[ i ] );
  }
  
  typedef size_t val_t[ 6 ];
  extern void* stack_top;
  
  void Func()
  {
    val_t val;
  
    TakePtr( (void**) &amp;val, ( (size_t) stack_top - (size_t) &amp;val ) / sizof( size_t ) );
  }
  </code></pre>
  
  <p>It compiles fine with gcc 4.8, mingw 4.7, cl 18.00. Which might make sense because just from the looks of it I'd say there is no violation here: yes there are 2 pointers pointing to the same variable, but the second one's value is immediately cast to a size_t which requires a temporary, so the pointer itself cannot be used inside the function TakePtr.</p>
  
  <p>Q1: Is my assumption above correct? And if it is, does this mean there really is no violation, or rather that the compiler figured out there is none while techically (i.e. following the standard by the letter) there is a violation (still two pointers to same variable being dereferenced)?</p>
  
  <p>Q2: I stumbled upon this while using the mingw cross-compiler version 4.2.1 on linux, it raises <code>warning: dereferencing type-punned pointer will break strict-aliasing rules</code> for the line with TakePtr. So the second question is actually like the first but in other words: is this compiler correct, or is it a bug, or would one rather call it 'compiler being too strict'?</p>
  
  <p>Q3: Wanting compilation without warnings for all aforementioned compilers, what would the most correct fix in code be (maybe not just for this case, but for a more general one where there is a violation of the rule and void** pointers are used)? It seems there are multiple ways to silence the compiler:</p>
  
  <pre><code>union { val_t* r; void** ptr; } cast_ = { &amp;val };
  void** ptr = cast_.ptr;
  </code></pre>
  
  <p>or</p>
  
  <pre><code>void* p1 = (void*) &amp;val;
  void** ptr = &amp;p1;
  </code></pre>
  
  <p>or even</p>
  
  <pre><code>void** ptr = (void**) (void*) &amp;val;
  </code></pre>
  
  <p>or maybe (to tell the compiler 'hey I know what I'm doing', at least if I understood <code>restrict</code> correctly)</p>
  
  <pre><code>void* restrict p1 = (void*) &amp;val;
  void** ptr = &amp;p1;
  </code></pre>
  
  <p>or</p>
  
  <pre><code>val_t* p1 = &amp;val;
  void** p2 = NULL;
  memcpy( p2, p1, sizeof( p1 ) );
  </code></pre>