title: Unexpected sign extension of int32 or 32bit pointer when converted to uint64
body: <p>I compiled this code using Visual Studio 2010 (<code>cl.exe /W4</code>) as a C file:</p>
  
  <pre><code>int main( int argc, char *argv[] )
  {
      unsigned __int64 a = 0x00000000FFFFFFFF;
      void *orig = (void *)0xFFFFFFFF;
      unsigned __int64 b = (unsigned __int64)orig;
      if( a != b )
          printf( " problem\ta: %016I64X\tb: %016I64X\n", a, b );
      return;
  }
  </code></pre>
  
  <p>There are no warnings and the result is:</p>
  
  <blockquote>
    <p>problem        a: 00000000FFFFFFFF     b: FFFFFFFFFFFFFFFF</p>
  </blockquote>
  
  <p>I suppose <code>int orig = (int)0xFFFFFFFF</code> would be less controversial as I'm not assigning a pointer to an integer. However the result would be the same.</p>
  
  <p>Can someone explain to me where in the C standard it is covered that <code>orig</code> is sign extended from 0xFFFFFFFF to 0xFFFFFFFFFFFFFFFF?</p>
  
  <p>I had assumed that <code>(unsigned __int64)orig</code> would become 0x00000000FFFFFFFF. It appears that the conversion is first to the signed __int64 type and then it becomes unsigned?<br>
  <br></p>
  
  <p>EDIT: This question has been answered in that pointers are sign extended which is why I see this behavior in gcc and msvc. However I don't understand why when I do something like <code>(unsigned __int64)(int)0xF0000000</code> it sign extends to 0xFFFFFFFFF0000000 but <code>(unsigned __int64)0xF0000000</code> does not instead showing what I want which is 0x00000000F0000000.</p>
  
  <p>EDIT: An answer to the above edit. The reason that <code>(unsigned __int64)(int)0xF0000000</code> is sign extended is because, as noted by user <a href="https://stackoverflow.com/users/379897/r">R</a>:</p>
  
  <blockquote>
    <p>Conversion of a signed type (or any type) to an unsigned type
    <strong>always</strong> takes place via reduction modulo one plus the max value of
    the destination type.</p>
  </blockquote>
  
  <p>And in <code>(unsigned __int64)0xF0000000</code>  0xF0000000 starts off as an unsigned integer type because it cannot fit in an integer type. Next that already unsigned type is converted <code>unsigned __int64</code>.</p>
  
  <p>So the takeaway from this for me is with a function that's returning a 32-bit or 64-bit pointer as an <code>unsigned __int64</code> to compare I must first convert the 32-bit pointer in my 32-bit application to an unsigned type before promoting to <code>unsigned __int64</code>. The resulting code looks like this (but, you know, better):</p>
  
  <pre><code>unsigned __int64 functionidontcontrol( char * );
  unsigned __int64 x;
  void *y = thisisa32bitaddress;
  x = functionidontcontrol(str);
  if( x != (uintptr_t)y )
  </code></pre>
  
  <p><br><br>
  EDIT again:
  Here is what I found in the C99 standard:
  6.3.1.3 Signed and unsigned integers</p>
  
  <ul>
  <li>1 When a value with integer type is converted to another integer
  type other than _Bool, if the value can be represented by the new
  type, it is unchanged.</li>
  <li>2 Otherwise, if the new type is unsigned, the value is converted by
  repeatedly adding or subtracting one more than the maximum value
  that can be represented in the new type until the value is in the
  range of the new type.49)</li>
  <li>3 Otherwise, the new type is signed and the value cannot be
  represented in it; either the result is implementation-defined or an
  implementation-defined signal is raised.</li>
  <li>49) The rules describe arithmetic on the mathematical value, not the
  value of a given type of expression.</li>
  </ul>