我正在使用Visual Studio 2017开发Windows操作系统,并且我从SO的答案之一获得了以下函数来确定文件的大小:
__int64 FileSize(const char *filename)
{
HANDLE hFile = CreateFile(filename, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
return -1; // error condition, could call GetLastError to find out more
}
LARGE_INTEGER size;
if (!GetFileSizeEx(hFile, &size)) {
CloseHandle(hFile);
return -1; // error condition, could call GetLastError to find out more
}
CloseHandle(hFile);
return size.QuadPart;
}
因此,我正在使用它来确定文件大小,以便使用malloc()
相应地动态分配内存。由于函数malloc()
接受size_t
类型,我将FileSize()
函数的返回值赋给size_t变量,但我收到以下警告:
main.cpp(67):警告C4244:'初始化':从'__int64'转换为':: size_t',可能会丢失数据
在这种情况下,我如何安全地将文件大小存储在size_t
变量中?我知道我可以将返回值转换为size_t
并忽略警告,但是它是否安全/正确?
答案 0 :(得分:4)
这是特定于系统的。在某些系统上,size_t
可能小于int64_t
,这会发出警告。但是当然你不能在size_t
内适应malloc。
size_t s = (size_t)some_int64;
最有可能安全。
但是,如果你感到偏执,你可以添加一个检查/断言:
#include <stdint.h>
...
if(some_int64 > SIZE_MAX) // this line is fully portable
{
halt_and_catch_fire();
}
SIZE_MAX
是一个常量,表示size_t
变量可以容纳的最大值。
答案 1 :(得分:1)
size_t类型是实现定义的。 因此无法确定__int64的值是否可以安全地存储在size_t类型中。 我建议使用static_assert:
static_assert(sizeof(__int64)<=sizeof(size_t),
"Unable to safely store an __int64 value in a size_t variable");
如果size_t小于__int64,则会在编译过程中产生错误。
答案 2 :(得分:1)
size_t
小于__int64
。
如果您知道您正在使用的文件是“小”(<2 GB),您可以通过强制转换来回避问题,如果文件在某种程度上非常大,则只是中止:
UINT64 size = FileSize(...);
if (size > ~(size_t)0) // You might want to use SIZE_MAX instead of the ~ trick if you want to stay portable
{
printf("File is too large!\n");
}
else
{
void*data = malloc((size_t) size);
if (!data)
printf("Out of memory, file is too large?\n");
else
...
}
另一方面,如果文件可能很大,那么您不能假设您可以立即将整个内容读入内存,因为机器可能没有足够的内存或者您可能用完了地址空间(通常是在32位Windows进程中为2 GB)。在这种情况下,您应该使用memory mapped files而不是较小的视图。
答案 3 :(得分:0)
如果您正在编译32位,size_t
将只是32位。
因此,建议您返回size.LowPart
,如果size.HighPart
不为零,则忽略或错误。