FILETIME до __int64
Как правильно конвертировать FILETIME
структурировать в __int64
? Подскажите пожалуйста?
7 ответов
Я не думаю, что вы предполагаете: "Не бросайте указатель на FILETIME
структура либо ULARGE_INTEGER*
или же __int64*
значение, потому что это может вызвать ошибки выравнивания в 64-битной Windows."
Если бы вы действительно хотели, это было бы что-то вроде:
__int64 to_int64(FILETIME ft)
{
return static_cast<__int64>(ft.dwHighDateTime) << 32 | ft.dwLowDateTime;
}
FILETIME ft = // ...
__int64 t = to_int64(ft);
Но что-то вроде:
FILETIME ft = // ...
__int64 t = *reinterpet_cast<__int64*>(&ft);
Плохо.
Нет необходимости возвращаться к тайным конструкциям с использованием побитового ИЛИ. Windows API имеет все необходимое для этого.
unsigned __int64 convert( const FILETIME & ac_FileTime )
{
ULARGE_INTEGER lv_Large ;
lv_Large.LowPart = ac_FileTime.dwLowDateTime ;
lv_Large.HighPart = ac_FileTime.dwHighDateTime ;
return lv_Large.QuadPart ;
}
Или, если вы хотите перейти к __int64 напрямую.
__int64 convert_to_int64( const FILETIME & ac_FileTime )
{
return static_cast< __int64 > ( convert( ac_FileTime ) ) ;
}
Пытаться
(__int64(filetime.dwHighDateTime)<<32) | __int64(filetime.dwLowDateTime)
Конечно, вы можете просто передать __int64, приведенное к времени файла, следующим образом *(FILETIME*)&int64Val. Это будет хорошо работать под Visual C++.
т.е.
__int64 createTime = 0;
__int64 accessTime = 0;
__int64 writeTime = 0;
GetFileTime( hFile, *(FILETIME*)&createTime, *(FILETIME*)&accessTime, *(FILETIME*)&writeTime );
Вы можете попробовать следующий код. код из хромового проекта
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
//FILETIME to __int64
__int64 FileTimeToMicroseconds(const FILETIME& ft) {
return bit_cast<__int64, FILETIME>(ft) / 10;
}
void MicrosecondsToFileTime(__int64 us, FILETIME* ft) {
*ft = bit_cast<FILETIME, __int64>(us * 10);
}
int _tmain(int argc, _TCHAR* argv[])
{
__int64 nTmpUint64 = 13060762249644841;
time_t unixtime;
FILETIME nTmpFileTm;
MicrosecondsToFileTime(nTmpUint64,&nTmpFileTm);
return 0;
}
Три способа, которые имеют наилучшую производительность (одна инструкция на ассемблере). Протестировано только в Visual C++ 2022 x64.
auto u = std::bit_cast<std::uint64_t>(ft)
Лучший путь.
auto u = *reinterpret_cast<std::uint64_t _UNALIGNED*>(&ft)
Недостаток:_UNALIGNED
макрос (и__unaligned
модификатор) является нестандартным. Но почти у каждого компилятора есть этот модификатор в той или иной форме.
memcpy(&u, &ft, sizeof(u))
Недостаток: этот код будет хорошо оптимизирован, только если вы включите опцию компилятора C++ «Enable Intrinsic Functions».
Другие ответы имеют некоторые накладные расходы.
(static_cast<std::uint64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime
Генерирует побитовые операции.
ULARGE_INTEGER{ft.dwLowDateTime, ft.dwHighDateTime}.QuadPart
Генерирует две 32-битные операции вместо одной 64-битной.
У меня была точно такая же проблема, я искал ее в Google и пришел сюда. Но я также нашел полезную страницу поддержки Microsoft по адресу
https://support.microsoft.com/en-gb/help/188768/info-working-with-the-filetime-structure
Он говорит:
Выполнение арифметики с указанием времени файла
Часто бывает необходимо выполнить простую арифметику над временем файла. Например, вам может потребоваться узнать, когда файлу 30 дней. Чтобы выполнить арифметические действия с файловым временем, вам необходимо преобразовать FILETIME в четверное слово (64-битное целое число), выполнить арифметические действия, а затем преобразовать результат обратно в FILETIME.
Предполагая, что ft - это структура FILETIME, содержащая время создания файла, следующий пример кода добавляет 30 дней ко времени:
ULONGLONG qwResult;
// Copy the time into a quadword.
qwResult = (((ULONGLONG) ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
// Add 30 days.
qwResult += 30 * _DAY;
// Copy the result back into the FILETIME structure.
ft.dwLowDateTime = (DWORD) (qwResult & 0xFFFFFFFF );
ft.dwHighDateTime = (DWORD) (qwResult >> 32 );
Изменить: я понимаю, что это просто подтверждает некоторые другие ответы, но я подумал, что это стоит добавить для разъяснения.