FILETIME类型到LARGE_INTEGER类型的转换
核心编程第5版 245页到247页的讲到SetWaitableTimer函数的使用
其中提到 FILETIME类型到LARGE_INTEGER类型的转换问题,如下代码
//我们声明的局部变量 HANDLE hTimer; SYSTEMTIME st; FILETIME ftLocal, ftUTC; LARGE_INTEGER liUTC; //创建自动重置计时器 hTimer = CreateWaitableTimer(NULL,FALSE,NULL); //第一次触发时间是在2008年1月1日,在下午1:00(当地时间)。 st.wYear = 2008; //年 st.wMonth = 1; //1月 st.wDayOfWeek = 0; //忽略 st.wDay = 1; //1日 st.wHour = 13; //下午1点 st.wMinute = 0; //一个小时的第0分 st.wSecond = 0; //一个分钟的第0秒 st.wMilliseconds = 0; //一秒的第0毫秒 SystemTimeToFileTime(&st, &ftLocal); //将本地时间转换为UTC时间 LocalFileTimeToFileTime(&ftLocal, &ftUTC); //转换 FILETIME类型 为 LARGE_INTEGER类型 因为这2个类型的对齐方式不同 liUTC.LowPart = ftUTC.dwLowDateTime; liUTC.HighPart = ftUTC.dwHighDateTime; //设置时间 SetWaitableTimer(hTimer, &liUTC, 6 * 60 * 60 * 1000, NULL, NULL, FALSE);书上说到
虽然FILETIME 结构和LARGE_INTEGER结构具有完全相同的二进制格式,但是这两个结构的对齐方式是不同的。所有FILETIME结构的地址必须对齐到32位边界(即地址是4的整数倍),而所有LARGE_INTEGER结构的地址则必须对齐到64位边界(即地址是8的整数倍)。调用SetWaitableTimer并传入FILETIME结构是否能够正常工作,取决于FILETIME结构是否正好在64位边界上。但是,编译器会确保LARGE_INTEGER结构的地址始终都在64位边界上,因此正确的做法(任何时候都能够正常工作的做法)是先把FILETIME的成员复制到LARGE_INTEGER的成员中,然后再把LARGE_INTEGER的地址传给SetWaitableTimer。