title: If a `uintptr_t` can be used to store both pointers and numbers, why can't a `void*` do the same?
body: <p>Enumerations in languages like e.g. Swift or Rust support a kind of hybrid &quot;choice <em>plus</em> data&quot; mechanism, such that I could define a type like:</p>
  <pre><code>enum SomeOption {
    None,
    Index(int),
    Key(string),
    Callback(fn),
  }
  </code></pre>
  <p>Now if I were to implement this in C, my understanding is that something like this would <strong>not</strong> be valid:</p>
  <pre class="lang-c prettyprint-override"><code>typedef enum {
    is_callback_or_none,
    is_string,
    is_number
  } my_choice;
  
  typedef struct {
     my_choice value_type;
     void* value;
  } my_option;
  
  my_option x = {
    .value_type = is_number,
    .value = (void*)42
  };
  if (x.value_type == is_number) {
    int n = (int)x.value;
    // … use n…
  }
  </code></pre>
  <p>I'm not sure what exactly I risk in doing this, but according to e.g. <a href="https://stackoverflow.com/questions/25313926/can-pointers-store-values-and-what-is-the-use-of-void-pointers/25315105#25315105">Can pointers store values and what is the use of void pointers?</a> the only things I should store in a <code>void*</code> are actual addresses and <code>NULL</code>. [Aside: please turn a blind eye to the separate question of storing callback <em>function</em> pointers in a <code>void*</code> which I forgot was <a href="https://stackoverflow.com/questions/36645660/why-cant-i-cast-a-function-pointer-to-void/53029117#53029117">problematic</a> when I made up this example.]</p>
  <p>I suppose a more proper way to do this would be to use a union, e.g.:</p>
  <pre><code>typedef struct {
     my_choice value_type;
     union {
        int number_value;
        char* string_value;
        void* pointer_value;
     };
  } my_option;
  </code></pre>
  <p>…which is probably nicer all around anyway. <strong>But</strong> I'm wondering specifically about the invalidity of the <code>void* value</code> version . What if I were (instead of the <code>union</code> solution) to simply substitute <code>uintptr_t</code> in place of the <code>void*</code>?</p>
  <pre><code>typedef struct {
     my_choice value_type;
     uintptr_t value;
  } my_option;
  </code></pre>
  <p>Would storing <em>either</em> a pointer to a string/callback/null <em>or</em> a number within the <code>uintptr_t value</code> field of this struct be valid and [at least POSIX-]portable code? And if so, why is that okay, but not the seemingly equivalent <code>void* value</code> version?</p>