简体   繁体   English

隐式转换加倍到无符号长溢出c ++

[英]Implicit conversion double to unsigned long overflow c++

I'm testing a timer based on the ctime library using the clock() function. 我正在使用clock()函数测试基于ctime库的计时器。 Please note that the code that follows is only for test purposes. 请注意,以下代码仅用于测试目的。

#include <ctime>

unsigned long Elapsed(void);

clock_t start = 0;
clock_t stop = 0;

int main()
{
  start = std::clock();
  while(1)
   {
    sleep(1);
    cout << "Elapsed seconds: " << Elapsed() << endl;
   }
return 0;
}

unsigned long Elapsed()
{
  stop = std::clock();
  clock_t ticks = stop - start;
  double seconds = (double)ticks / CLOCKS_PER_SEC;  //CLOCK_PER_SEC = 1 milion
  return seconds;
}

As you can see I'm performing an implicit conversion from double to unsigned long when Elapsed() returns the calculated value. 正如您所看到的,当Elapsed()返回计算值时,我正在执行从double到unsigned long的隐式转换。 The unsigned long limit for a 32 bit system is 2,147,483,647 and I get overflow after Elapsed() returns 2146. 32位系统的无符号长限是2,147,483,647,并且在Elapsed()返回2146后我得到溢出。

Looks like the function converts "ticks" to unsigned long, CLOCK_PER_SEC to unsigned long and then it returns the value. 看起来该函数将“ticks”转换为unsigned long,CLOCK_PER_SEC转换为unsigned long,然后返回该值。 When it converts the "ticks" it overflows. 当它转换“滴答”时它会溢出。

I expected it, instead, to first calculate the value in double of "ticks"/CLOCK_PER_SEC and THEN convert it to unsigned long. 相反,我期望首先计算“ticks”/ CLOCK_PER_SEC的两倍的值,然后将其转换为unsigned long。

In the attempt to count more seconds I tried to return a unsigned long long data type, but the variable always overflows at the same value (2147). 在尝试计算更多秒时,我尝试返回无符号长long数据类型,但变量总是以相同的值溢出(2147)。

Could you explain me why the compiler converts to unsigned long long "a priori" and why even with unsigned long long it overflows at the same value ? 你能解释一下为什么编译器转换为无符号long long“先验”,为什么即使使用unsigned long long也会溢出相同的值? Is there any way to write the Elapsed() function in a better way to prevent the overflow to happen ? 有没有办法以更好的方式编写Elapsed()函数来防止溢出发生?

Contrary to popular belief, the behaviour on converting a floating point type such as a double to any integral type is undefined if the value cannot fit into that integral type. 与流行的看法相反,如果值不能适合该整数类型,则将浮点类型(如double任何整数类型的行为是不确定的。

So introducing a double in your function is a poor thing to do indeed. 因此,在你的功能中引入double是一件很糟糕的事情。

Why not write return ticks / CLOCKS_PER_SEC; 为什么不写return ticks / CLOCKS_PER_SEC; instead if you can allow for truncation and wrap-around effects? 相反,如果你可以允许截断和环绕效果? Or if not, use a unsigned long long as the return value. 或者如果不是,请使用unsigned long long作为返回值。

If on your system, clock_t is a 32 bit type, then it's likely it'll wrap around after 2147 seconds like you're seeing. 如果在你的系统上, clock_t是一个32位类型,那么它很可能会像你看到的那样在2147秒后回绕。 This is expected behavior (ref. clock ). 这是预期的行为(参考clock )。 And no amount of casting will get around that. 并没有任何数量的铸造可以解决这个问题。 Your code needs to be able to deal with the wrap-around (either by ignoring it, or by explicitly accounting for it). 您的代码需要能够处理环绕(通过忽略它,或通过明确地考虑它)。

When it converts the "ticks" it overflows. 当它转换“滴答”时它会溢出。

No, the clock itself "overflows"; 不,时钟本身“溢出”; the conversion has nothing to do with it. 转换与它无关。 That said, the conversion to double is pointless. 也就是说,转换为double是毫无意义的。 Your limitation is the type clock_t . 您的限制是类型clock_t See notes for example from this reference : 请参阅此参考中的注释:

The value returned by clock() may wrap around on some implementations. clock()返回的值可能会包含在某些实现中。 For example, on a machine with 32-bit clock_t, it wraps after 2147 seconds or 36 minutes. 例如,在具有32位clock_t的机器上,它在2147秒或36分钟后换行。

One alternative, if it's available to you, is to rely on POSIX standard instead of C standard library. 如果可以使用的话,另一种选择是依赖POSIX标准而不是C标准库。 It provides clock_gettime which can be used to get the CPU time represented in timespec . 它提供了clock_gettime ,可用于获取timespec表示的CPU时间。 Not only does it not suffer from this overlflow (until much longer timespan), but it also may have higher resolution than clock . 它不仅不会受到这种过度放电(直到更长的时间跨度),而且它的分辨率也可能高于clock The linked reference page of clock() conveniently shows example usage of clock_gettime as well. clock()的链接参考页面也方便地显示了clock_gettime示例用法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM