这是第二次写关于__int64的文章了,问题与上次类似,出现问题的原因也一样。不过让我找了几天的BUG总得记下来!
先上一段测试代码:
int _tmain(int argc, _TCHAR* argv[])
{
__int64 i64 = -sizeof(int);
__int64 j64 = -4;
cout << "i64 = " << i64 << endl;
cout << "j64 = " << j64 << endl;
int i4 = -sizeof(int);
int j4 = -4;
cout << "i4 = " << i4 << endl;
cout << "j4 = " << j4 << endl;
return 0;
}
猜猜上面程序的输出结果?
是这样的吗?
-4
-4
-4
-4
如果你的结果是这样,那么你只能得75分,还有25分去哪儿了?
第一个-4是错误的!
为什么?先看看运行结果:
第一个为什么不是-4呢?再看看这个图吧
4294967292,跟上面运行结果是一样的!这下明白了,在编译阶段,-sizeof(int)被当成一个32位的整形对待,二进制表示为:
1111 1111 1111 1111 1111 1111 1111 1100(-4的二进制表示)。而__int64是一个64位的,所以完全可以把1111 1111 1111 1111 1111 1111 1111 1100存放下来,而不发生数据截断。所以此时1111 1111 1111 1111 1111 1111 1111 1100被解释成4294967292,而不是-4!
现在可以向大家展示这段让我改了好几天的代码了(详见注释):
//在文件结尾的地方记录当前文件指针位置
LARGE_INTEGER liMov, liCurPtr;
liMov.QuadPart = 0;
liCurPtr.QuadPart = 0;
if (SetFilePointerEx(hFile, liMov, &liCurPtr, FILE_CURRENT))
{
liMov.QuadPart = -sizeof(LARGE_INTEGER); //错误出现在这里:liMov结果不是-8!
if (SetFilePointerEx(hFile, liMov, NULL, FILE_END)) //这里文件被“撑大了”
{
DWORD dwBytesWrite = 0;
WriteFile(hFile, (LPVOID)&liCurPtr, sizeof(LARGE_INTEGER), &dwBytesWrite,
NULL); /*由于文件大小被上面的SetFilePointerEx“撑大了”,所以这里会不停地写,直到填满“文件空洞”。虽然你只想写sizeof(LARGE_INTEGER)那个多字节,但是文件系统会很“贴心”地帮你填补空洞!*/
}
else
{
}
}
补充一下:上面由于文件指针的移动而造成的文件空洞最后会由文件系统帮你填补上,所以即使你的程序已经退出,在任务管理器里面仍然可以看到。如果通过Process Monitor可以看到进程正在进行写文件操作,每次写入大小512KB