Re: unsigned __int64 typecast bug?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



On Sat, 27 May 2006 12:12:42 -0700, <test> wrote:

This does not seem like correct behavior.
Running on Windows XP SP2 32bit
Have tested this with VS 2003 C complier and WS2003 SP1 DDK.

The code below will generate the following results:
good= f1111000, nosign= 4fffffff, badsign= fffffffff1111000, uito64=
f1111000

The typecast of a 32 bit pointer to (unsigned __int64) is causeing sign
extension. The typecast does the correct thing for an unsigned int, but not
pointers.

Why would one do this? Well I had an unsigned _int64 array of debug info I
was passing from driver to app and thought hey I could throw a few buffer
addresses in there and it would be easy to dump them with the rest of the
data.
It works correctly if I typecast to (unsigned int), but that seems like an
odd way of doing this.
Cliff

int _tmain(int argc, _TCHAR* argv[])

{

unsigned __int64 good, badsign, nosign, uito64;

unsigned int *ptr, *ptr2;

unsigned int ui;

ptr = (unsigned int *)0xf1111000; // 32bit addr high bit set

ptr2 = (unsigned int *)0x4fffffff; // 32bit addr high bit not set

badsign = (unsigned __int64) ptr;

nosign = (unsigned __int64) ptr2;

good = (unsigned int) ptr;

ui = 0xf1111000;

uito64 = (unsigned __int64) ui;

This last cast is unnecessary.

printf("good= %I64x, nosign= %I64x, badsign= %I64x, uito64= %I64x\n", good,
nosign, badsign,uito64);

return 0;

}

I don't know if the conversion sequence from 32 bit pointer to 64 bit
unsigned integer is documented, but the conversion from 32 bit pointer to
64 bit pointer does sign extend in Win64:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win64/win64/rules_for_using_pointers.asp
<q>
Be careful when using POINTER_32 values in code that may be compiled as
64-bit code. The compiler will sign-extend the pointer when it is assigned
to a native pointer in 64-bit code, not zero-extend the pointer.
</q>

If I were to guess, the compiler is widening the pointer to 64 bits and
then performing the cast, or maybe it's converting to a 32 bit int first,
but from a language standard point of view, all this is at best
implementation-defined and may be unspecified. Really all you can portably
do is cast back to the original type, which should produce the original
value. The intermediate values needn't be what you might expect, but it
looks like you've found a way to get what you want.

--
Doug Harrison
Visual C++ MVP
.



Relevant Pages

  • Re: struct named 0
    ... > that it is an expression with a value known to the compiler at COMPILE ... The conversion is done at RUN TIME in the abstract machine. ... > pointer, the value of that integer object is accessed and evaluated at ... > to that null pointer representation, or integers with the bit pattern ...
    (comp.lang.c)
  • Re: array of pointers
    ... Compiler is not happy with XXX line: ... My undestanding is that 'lineptr' is an array of pointers, ... The pointer type in this case is 'const char **' and the result of the conversion points to the first element of the array. ...
    (comp.lang.c)
  • Re: wrt my conservative static region allocator...
    ... presumably there IS no integral type that can represent a pointer. ... but I've seen compilers (like gcc) reject code which casted a pointer to ... thus a compiler might reject all attempts to cast to an integral ... so rejecting such a conversion would be non-conforming (unless, ...
    (comp.lang.c)
  • Re: Unions Redux
    ... pointer casting. ... union U {double a; unsigned int b;} u; ... valid and aliasing rules don't work here. ...
    (comp.lang.c)
  • Re: Initializer element not constant
    ... unsigned int, which I assume is 32 bits, would cause a nasty run-time ... problem, since first if any of the upper 32 bits of the pointer are 1, ... an object of this type with static storage duration you are trying to ... So your compiler, with one set of options, is quite free to reject ...
    (comp.lang.c)