我看到非常奇怪的问题。以某种方式使用我的下面的代码,我看到负数被打印出来,如下面的holder
变量所示。我不确定为什么会这样。
-2147483648 days -2147483648 hours -2147483648 minutes ago
这是我的时间戳(current_unix_timestamp)值1437943320
,它将传递给我的下方法,之后holder
值将会显示为上面所示为负数。
char holder[100];
get_timestamp_value(current_unix_timestamp, holder);
inline void get_timestamp_value(long sec_since_epoch_time, char* holder) {
uint64_t timestamp = current_timestamp();
double delta = timestamp/1000000 - sec_since_epoch_time;
int days = floor(delta/60/60/24);
int hours = floor((delta - days * 60 * 60 * 24)/60/60);
int minutes = floor((delta - days * 60 * 60 * 24 - hours * 60 * 60)/60);
holder[0] = 0;
if (days) sprintf(holder, "%d days ", days);
if (hours) sprintf(holder, "%s%d hours ", holder, hours);
sprintf(holder, "%s%d minutes ago", holder, minutes);
std::cout<< "Timestamp: " << timestamp << ", sec_since_epoch_time: " << sec_since_epoch_time << ", Delta:" << delta << ", Days: " << days << ", hours: " << hours << ", mins: " << mins << std::endl;
}
// get current system time in microseconds since epoch
inline uint64_t current_timestamp()
{
std::chrono::time_point<std::chrono::steady_clock> ts = std::chrono::steady_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(ts.time_since_epoch()).count();
}
现在这是从上面cout
日志中打印出来的内容:
Timestamp: 433430278724, sec_since_epoch_time: 1437943320, Delta:1.84467e+19, Days: -2147483648, hours: -2147483648, mins: -2147483648
Timestamp: 433679536303, sec_since_epoch_time: 1437943380, Delta:1.84467e+19, Days: -2147483648, hours: -2147483648, mins: -2147483648
Timestamp: 433929683258, sec_since_epoch_time: 1437943440, Delta:1.84467e+19, Days: -2147483648, hours: -2147483648, mins: -2147483648
Timestamp: 434179628271, sec_since_epoch_time: 1437943500, Delta:1.84467e+19, Days: -2147483648, hours: -2147483648, mins: -2147483648
上述代码中是否发生了导致此问题的错误?任何建议都会有很大的帮助。
答案 0 :(得分:1)
您应该尽量避免使用有符号和无符号整数类型的混合进行算术运算。结果往往令人惊讶。
显然,timestamp
不是您期望的值,因为timestamp/1000000
是433430,远远小于sec_since_epoch_time
。因此,您可能希望timestamp/1000000 - sec_since_epoch_time
为负数,但(令人惊讶的是,如上所述),它将是一个大的正数,因为签名的长sec_since_epoch_time
先前已转换为unsigned long
减法,遵循通常的算术转换规则。然后使用无符号算术完成减法,因此结果是一个略小于2 64 的正数,如delta
的值所示。
将该大数除以86400不足以使其达到int
的范围,因此分配
int days = floor(delta/60/60/24);
会溢出未定义的后果(在这种情况下,将days
设置为-2 31 。)
对我来说,要求持续时间以微秒为单位然后将它除以一百万,这似乎有点奇怪。为什么不在几秒钟内询问持续时间?
但潜在的问题是,您要将current_timestamp
返回的值(即std::chrono::steady_clock
纪元以来的微秒数)与参数sec_since_epoch_time
进行比较。在我看来,sec_since_epoch_time
是自Unix时代(1970年1月1日)以来的秒数。但是,无法保证std::chrono
时钟的纪元具有该值。 (显然,在Linux上,std::chrono:system_clock
的时代是系统时代,但我重复一遍,不能保证。)
你不能比较自纪元以来的两个&#34;秒#34;值,除非它们是同一时期以来的秒数。这意味着代码可以工作的唯一方式是,最初用于获取sec_since_epoch_time
值的时钟与您在current_timestamp
中使用的时钟相同。
除了确保timestamp
实际具有预期值之外,您还应将timestamp
更改为int64_t
(或将其转换为int64_t
以进行计算delta
)。