在 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位的。期望的行为是:
- 64 位:使用整个大小,即
li.QuadPart
- 32 位:如果大小>4GB,MapViewOfFile 无论如何都会失败。所以,只需使用
li.LowPart
.
在我看来,我需要用 #ifdef
s 来做这个 - 有没有更优雅的方法?
在一般情况下,使用 this trick,您可以这样做:
if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big();
size_t result = (size_t)(li.QuadPart);
编译器应将第一行优化为 64 位编译中的空操作。
(在您的特定情况下,您可能根本不需要它;代码已经失败了。)
注意: 正如评论中已经讨论的那样,在这种特殊情况下,如果可能的话,最好使用允许您的散列 API以块的形式散列数据。
我正在尝试将文件映射到内存,并计算其哈希值:
// 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位的。期望的行为是:
- 64 位:使用整个大小,即
li.QuadPart
- 32 位:如果大小>4GB,MapViewOfFile 无论如何都会失败。所以,只需使用
li.LowPart
.
在我看来,我需要用 #ifdef
s 来做这个 - 有没有更优雅的方法?
在一般情况下,使用 this trick,您可以这样做:
if (li.QuadPart > ((ULONGLONG)((size_t)(-1))) too_big();
size_t result = (size_t)(li.QuadPart);
编译器应将第一行优化为 64 位编译中的空操作。
(在您的特定情况下,您可能根本不需要它;代码已经失败了。)
注意: 正如评论中已经讨论的那样,在这种特殊情况下,如果可能的话,最好使用允许您的散列 API以块的形式散列数据。