Pod*_*rce 2 c++ integer-overflow ctime
我正在使用 Clock() 函数测试基于 ctime 库的计时器。请注意,下面的代码仅用于测试目的。
#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;
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,当 Elapsed() 返回计算值时,我正在执行从 double 到 unsigned long 的隐式转换。32 位系统的无符号长限制是 2,147,483,647,并且在 Elapsed() 返回 2146 后出现溢出。
看起来该函数将“ticks”转换为 unsigned long,将 CLOCK_PER_SEC 转换为 unsigned long,然后返回值。当它转换“刻度”时,它会溢出。
相反,我期望它首先计算“ticks”/CLOCK_PER_SEC 的双倍值,然后将其转换为无符号长整型。
在尝试计算更多秒数时,我尝试返回 unsigned long long 数据类型,但该变量总是在相同值(2147)处溢出。
您能否解释一下为什么编译器会“先验”转换为 unsigned long long 以及为什么即使使用 unsigned long long 它也会以相同的值溢出?有没有办法以更好的方式编写 Elapsed() 函数来防止溢出发生?
与流行的看法相反,如果值无法适合该整型,则将浮点类型(例如 a)转换double为任何整型的行为是未定义的。
所以double在你的函数中引入 a 确实是一件糟糕的事情。
return ticks / CLOCKS_PER_SEC;如果可以允许截断和环绕效果,为什么不直接写呢?或者如果没有,则使用 aunsigned long long作为返回值。