title: May a C compiler assume that a non-static local volatile variable is uninitialized?
body: <p>In some project, I must access the machine code instructions of a function for debugging reasons.</p>
  <p>My first approach (I decided to do it differently) was to convert a function pointer to the function to a data pointer using a <code>union</code> like this:</p>
  <pre><code>void exampleCode(void)
  {
      volatile union {
          uint8_t ** pptr;
          void (* pFunc)(void);
      } u;
      uint8_t ** copyPptr;
      uint8_t * resultPtr;
  
  #if 1
      u.pptr = (uint8_t **)0x10000000;
  #endif
      u.pFunc = &amp;myFunction;
      copyPptr = u.pptr;
  
      /* The problem is here: */
      resultPtr = copyPptr[109];
      *resultPtr = 0xA5;
  }
  </code></pre>
  <p>If I remove the line <code>u.pptr = (uint32_t **)0x10000000</code>, the compiler assumes that <code>copyPptr</code> two lines below has an undefined value (according to the C standard, converting function pointers to data pointers is not allowed).</p>
  <p>For this reason, it &quot;optimizes&quot; the last two lines out (which is of course not wanted)!</p>
  <p>However, the <code>volatile</code> keyword means that the C compiler must not optimize away the read operation of <code>u.pptr</code> in the line <code>copyPptr = u.pptr</code>.</p>
  <p>From my understanding, this also means that the C compiler must assume that it is at least possible that a &quot;valid&quot; result is read in this read operation, so <code>copyPptr</code> contains some &quot;valid&quot; pointer.</p>
  <p>(At least this is how I understand the answers to <a href="https://stackoverflow.com/questions/51472394/is-it-allowed-for-a-compiler-to-optimize-away-a-local-volatile-variable">this question</a>.)</p>
  <p>Therefore, the compiler should not optimize away the last two lines.</p>
  <p>Is this a compiler bug (GCC for ARM) or is this behavior allowed according to the C standard?</p>
  <p><strong>EDIT</strong></p>
  <p>As I have already written, I already have another solution for my problem.</p>
  <p>I asked this question because I'm trying to understand why the <code>union</code> solution did not work to avoid similar problems in the future.</p>
  <p>In the comments, you asked me for my exact use case:</p>
  <p>For debugging reasons, I need to access some <code>static</code> variable in some library that comes as object code.</p>
  <p>The disassembly looks like this:</p>
  <pre><code>.text
  .global myFunction
  myFunction:
      ...
  .L1:
      .word .theVariableOfInterest
  
  .data:
  # unfortunately not .global!
  .theVariableOfInterest:
      .word 0
  </code></pre>
  <p>What I'm doing is this:</p>
  <p>I set <code>copyPtr</code> to <code>myFunction</code>. If <code>K</code> is <code>(.L1-myFunction)/4</code>, then <code>copyPtr+K</code> points to <code>.L1</code> and <code>copyPtr[K]</code> points to <code>.theVariableOfInterest</code>.</p>
  <p>So I can access the variable using <code>*(copyPtr[K])</code>.</p>
  <p>From the disassembly of the object file, I can see that <code>K</code> is 109.</p>
  <p>All this works fine if <code>copyPtr</code> contains the correct pointer.</p>
  <p><strong>EDIT 2</strong></p>
  <p>It's much simpler to reproduce the problem with <code>gcc -O3</code>:</p>
  <pre><code>char a, c;
  char * b = &amp;a;
  
  void testCode(void)
  {
      char * volatile x;
      c = 'A';
      *x = 'X';
  }
  </code></pre>
  <p>It's true that uninitialized variables cause undefined behavior.</p>
  <p>However, if I understand the description of <code>volatile</code> in the draft &quot;ISO/IEC 9899:TC3&quot; of the C99 standard correctly, a <code>volatile</code> variable would not be &quot;uninitialized&quot; if I stop the program in the debugger (using a breakpoint) at the line <code>c = 'A'</code> and copy the value of <code>b</code> to <code>x</code> in the debugger.</p>
  <p>On the other hand, some other statement was saying that using <code>volatile</code> for local variables in current C++ (not C) versions already causes undefined behavior ...</p>
  <p>Now I'm wondering what is true for modern C (not C++) versions.</p>