Sign in to follow this  
wasted_druid

Hack Code and Why Does it work?

Recommended Posts

wasted_druid    692
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?

Share this post


Link to post
Share on other sites
Promit    13246
__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.

Share this post


Link to post
Share on other sites
wasted_druid    692
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.

;)

Share this post


Link to post
Share on other sites
ApochPiQ    23064
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]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this