c++:将__int64转换为unsigned long

C++: converting __int64 to unsigned long

本文关键字:unsigned long 转换 int64 c++      更新时间:2023-10-16

我想在windows和linux中使用以下函数,但我不确定如何将__int64转换为unsigned long。像我这样强制转换值安全吗?

getTimeInMilliseconds()
{
    #ifdef _WIN32

        static const __int64 magic = 116444736000000000; // 1970/1/1
        SYSTEMTIME st;
        GetSystemTime(&st);
        FILETIME   ft;
        SystemTimeToFileTime(&st,&ft); // in 100-nanosecs...
        __int64 t;
        memcpy(&t,&ft,sizeof t);
        return (unsigned long)((t - magic)/10000);
    #else
        struct timeval tv;
        gettimeofday(&tv, NULL);
        unsigned long s = tv.tv_sec * 1000;
        unsigned long us = tv.tv_usec / 1000;
        return s + us;
    #endif
}

是的,它是"安全的",从语法上讲,你可以做代码中写的事情。当将64位整型降级为32位长整型时,您自然会丢失前32位,如果您的值足够小,这不是问题,问题是您的值实际上不够小。

两个定义(WIN32和非WIN32)都有溢出问题,不是因为你不能将64位int类型强制转换为long类型,而是因为你试图将太大的值塞进太小的容器。

问题#1,函数名将结果描述为"以毫秒为单位的时间",这是假的,两个实现都试图以微秒(千分之一秒)返回结果,而不是以"毫秒"(百万分之一秒)返回结果。确定你真正想要的结果,并适当地给它贴上标签,减少长期的困惑。请注意,100纳秒(十亿分之一秒)的间隔与1/10毫秒相同,即1/10,000微秒,仅供参考。

问题# 2:将FILETIME结构体转换为长整型的"内存"也是错误的。FILETIME和__int64有不同的字节对齐方式,这样你会在错误的地方得到位。要将FILETIME转换为_int64类型,您需要这样做:

LARGE_INTEGER foo;
FILETIME baz;
__int64 bar;
foo.HighPart = baz.dwHighDateTime;
foo.LowPart = baz.dwLowDateTime;
bar = foo.Quadpart;

问题# 3:一个32位长的int只能存储足够大的时间值,以秒为单位,即使这样也只能到2038年初,这就是为什么"timeval"有一个单独的'微秒'成员,这不仅仅是为了让你的生活变得困难。

如果你想在单个值中每秒几千次,你至少需要36位,可能更像38-40,以便在比1970-2038更健壮的时间框架中引用值。由于很少有编译器支持40位整数,我建议升级到完整的64位,除非由于某些原因不能,在这种情况下,您应该为您正在尝试做的事情提出更好的解决方案。