【问题标题】:C++ Integer overflow problem when casting from double to unsigned int从 double 转换为 unsigned int 时的 C++ 整数溢出问题
【发布时间】:2011-03-08 07:55:36
【问题描述】:

我需要在 C++ 中将时间从一种格式转换为另一种格式,并且它必须是跨平台兼容的。我创建了一个结构作为我的时间容器。结构字段还必须是旧代码指定的unsigned int

struct time{   
unsigned int timeInteger;   
unsigned int timeFraction;
} time1, time2;

数学上的转换如下:

time2.timeInteger = time1.timeInteger + 2208988800

time2.timeFraction = (time1.timeFraction * 20e-6) * 2e32

这是我在 C++ 中的原始代码,但是当我尝试写入二进制文件时,转换后的时间与真实数据不匹配。我认为这个问题是由于类型转换错误造成的?此代码将在 VS2008 中编译并执行。

void convertTime(){
   time2.timeInteger  = unsigned int(time1.timeInteger + 2209032000);
   time2.timeFraction = unsigned int(double(time1.timeFraction) * double(20e-6)*double(pow(double(2),32)));
}

【问题讨论】:

  • @shuttle87:“更好”可以解释,但在这种情况下翻译为“不会编译”,很少有人发现它本身有改进。
  • @shuttle87: reinterpret_cast 不能用于转换数字类型;你需要static_cast。这不是使用 C 风格的转换,而是使用 C++ 初始化风格的转换。就个人而言,我发现数字转换比 static_cast 更容易。
  • 虽然我相信unsigned int(value)由于技术原因是无效的,但被大多数编译器接受。
  • @Mike 我用的是VS2008,代码会编译执行
  • 您确定要 2e32 而不是 pow(2,32) 吗?无论哪种方式,您的公式似乎都有点可疑。

标签: c++ datetime time casting type-conversion


【解决方案1】:

只是猜测,但您是否假设 2e32 == 2^32?如果您尝试将结果缩放为 32 位整数,则此假设是有意义的。其实2e32 == 2 * 10^32

【讨论】:

    【解决方案2】:

    有点不相关,我认为你应该重新考虑你的字体设计。您在这里基本上是在谈论两种 不同 类型。它们碰巧存储了相同的数据,尽管结果不同。

    为了最大限度地减少它们的使用错误,您应该将它们定义为两个完全不同的类型,它们之间具有明确定义的转换。

    举个例子:

    struct old_time {
        unsigned int timeInteger;   
        unsigned int timeFraction;
    };
    
    struct new_time {
    public:
        new_time(unsigned int ti, unsigned int tf) :
            timeInteger(ti), timeFraction(tf) { }
    
        new_time(new_time const& other) :
            timeInteger(other.timeInteger),
            timeFraction(other.timeFraction) { }
    
        new_time(old_time const& other) : 
            timeInteger(other.timeInteger + 2209032000U),
            timeFraction(other.timeFraction * conversion_factor) { }
    
        operator old_time() const {
            old_time other;
            other.timeInteger = timeInteger - 2209032000U;
            other.timeFraction = timeFraction / conversion_factor;
            return other;
        }
    
    private:
        unsigned int timeInteger;   
        unsigned int timeFraction;
    };
    

    (编辑:当然,由于下面指出的原因,此代码不起作用。

    现在可以以安全的方式无摩擦地使用此代码:

    time_old told; /* initialize … */
    
    time_new tnew = told; // converts old to new format
    time_old back = tnew; // … and back.
    

    【讨论】:

    • 我想我会听从您的建议并将它们定义为不同的类型,但这无助于转换问题,因为在上面的代码中,转换因子会产生整数溢出。但是请不要删除上面的代码,很有用的
    • @Elpezmuerto:是的,很抱歉我无法解决最初的问题……目前我无法解决这个问题,因为转换因子显然不适合一个unsigned int
    • 我认为目标是正确处理在 C 和 C++ 中会导致“环绕”的整数溢出。也许我可以为与 2^32 关联的所有零创建一个单独的变量,并将 timeFraction 分解为 charshort 并分段写入我的二进制文件,而不是一个完整的 unsigned int
    【解决方案3】:

    问题是 (20 ^ -6) * (2 e32) 远大于 UINT_MAX。也许您的意思是 2 的 32 次方或 UINT_MAX,而不是 2e32。

    此外,您的第一行是整数,初始值必须小于 (2^32 - 2209032000),并且根据测量值,它也可以环绕。在我看来,将第一个值设置为 long long(通常为 64 位)并更改 2e32。

    如果您无法更改类型,则可能需要存储该字段,因为它的结果是双精度,然后在使用前转换为 unsigned int。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-07
      • 1970-01-01
      • 1970-01-01
      • 2015-12-01
      • 2014-04-05
      • 2012-04-28
      • 1970-01-01
      • 2016-12-20
      相关资源
      最近更新 更多