在 32 位和 64 位代码中将 LARGE_INTEGER 映射到 SIZE_T

Mapping LARGE_INTEGER to SIZE_T in both 32-bit and 64-bit code

我正在尝试将文件映射到内存,并计算其哈希值:

// Declaration in header file which I don't control
void SymCryptSha256(PCBYTE pbData, SIZE_T cbData, PBYTE pbResult);

// MY code
HANDLE hFile = ::CreateFile(...);
HANDLE hMap = ::CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0, 0, nullptr));
byte* pMap = ::MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);

BYTE[64] hash;
ULARGE_INTEGER li;
li.LowPart = ::GetFileSize(file , &li.HighPart);
// This compiles in 64-bit, but errors in 32-bit:
// error C4244: 'argument': conversion from 'ULONGLONG' to 'SIZE_T', possible loss of data
::SymCryptSha256(pMap, li.QuadPart, &hash);

这是因为SymCryptSha256的第二个参数是SIZE_T,在32位编译中是32位的。期望的行为是:

在我看来,我需要用 #ifdefs 来做这个 - 有没有更优雅的方法?

在一般情况下,使用 this trick,您可以这样做:

if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big();
size_t result = (size_t)(li.QuadPart);

编译器应将第一行优化为 64 位编译中的空操作。

(在您的特定情况下,您可能根本不需要它;代码已经失败了。)

注意: 正如评论中已经讨论的那样,在这种特殊情况下,如果可能的话,最好使用允许您的散列 API以块的形式散列数据。