Hack Code and Why Does it work?

Started by
2 comments, last by ApochPiQ 18 years, 10 months ago
I was finding out about QueryPerformanceCounter, and found this snippet of code:

#pragma unmanaged

extern "C"
{
    int __stdcall QueryPerformanceCounter(__int64* p);
    int __stdcall QueryPerformanceFrequency(__int64* p);
}

#pragma managed
I liked it because when I used it, I had a call to QueryPerformanceCounter that didn't deal with those atrocious LARGE_INTEGERS. I'm programming in C++, and I got all my timer stuff working. But someone pointed out to me that I had no idea what I was doing here... a fact which I was trying to ignore. My question is: why does this work? How does it work?
----------------------------------------------------------No matter how eloquently you state your argument, the fact remains that the toilet seat is a bistable device. Therefore it's natural position is no more down than it is up.[SDL Smooth Tile Scrolling]
Advertisement
__int64 is a Visual Studio specific keyword for a 64 bit integer. On a 32 bit platform, it's basically just hiding all of the work required to deal in 64 bit integers that are split up into 2 32 bit integers, which is nice.

It is also set up to access the DLL calls for those two functions. From the pragma at the top, I gather this is managed C++? You probably don't need to put the calls in an extern "C" block, but I'm not really sure.
SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.
Actually it's not managed C++. I just found a block of code out there... can't even remember where... and stuck it in my app. I left it alone because it worked.

;)
----------------------------------------------------------No matter how eloquently you state your argument, the fact remains that the toilet seat is a bistable device. Therefore it's natural position is no more down than it is up.[SDL Smooth Tile Scrolling]
This works because of how structs are stored in memory. The strict definition of LARGE_INTEGER, according to MSDN, is as follows:

typedef union _LARGE_INTEGER {   struct {      DWORD LowPart;       LONG  HighPart;   };  LONGLONG QuadPart;} LARGE_INTEGER, *PLARGE_INTEGER;



Let's break this down. A union, as you may or may not be aware, has each of its members starting at the same location in memory. This means that the struct and the LONGLONG will both overlap the same bytes in memory. LONGLONG is, of course, a typedef for long long, which is (on a 32-bit platform) equivalent to __int64. [Note carefully, however, that on a 64-bit platform, an int is natively 64 bits, which breaks the long long == __int64 equivalency. Just a bit of portability trivia.]

Now, let's back up and look at the struct. A DWORD is basically a long which is 32 bits. A LONG is also 32 bits. In memory, each member of a struct immediately follows the previous member, so the total size of the struct is 64 bits of consecutive memory. Since a LARGE_INTEGER is a union, these 64 bits will directly overlap the same 64 bits of memory as QuadPart.

In memory, a LARGE_INTEGER is essentially a 64-bit integer, which is why you can get the equivalent data out of it by casting a PLARGE_INTEGER to __int64*. Internally, as Promit said, this is still reduced to multiple operations on two 32-bit chunks on a native 32-bit processor. The union is provided mainly to make the data type easily accessible in 32-bit chunks. Unions are a fairly handy (if not long-handed) method of breaking up a memory range into various sizes. For instance, you can extract the high and low words of a DWORD as follows:

typedef union _EASY_DWORD{   // WARNING: assumes a little-endian machine. Reverse these on big-endian platforms.   struct   {     WORD low;     WORD high;   };   DWORD dword;} EASY_DWORD;EASY_DWORD edw.dword = some_dword;cout << "The low word is " << edw.low << endl;




Interestingly, MSDN has this to say:

Quote:The LARGE_INTEGER structure is actually a union. If your compiler has built-in support for 64-bit integers, use the QuadPart member to store the 64-bit integer. Otherwise, use the LowPart and HighPart members to store the 64-bit integer.



So there's your marginally useless trivia for the day [wink]

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement