我正在使用Visual Studio 2017在Windows OS上工作,我获得了以下功能,以确定一个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
并删除警告,但这会安全/正确吗?
这是非常特定于系统的。在某些系统上,size_t
可能小于int64_t
,这会发出警告。但是,当然,无论如何,您都不能超越size_t
内的东西。
最有可能安全执行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
变量可容纳的最大值。
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,这将在编译过程中造成错误。
请参阅http://en.cppreference.com/w/cpp/types/size_t有关更多信息。
size_t
在编译32位应用程序时小于__int64
。
如果您知道正在使用的文件是"小"(&lt; 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)。在这种情况下,您应该使用较小视图的内存映射文件。
如果您要编译32位,则size_t
仅为32位。
因此,建议您返回size.LowPart
,如果size.HighPart
不是零,则忽略或错误。