我使用difftime的c函数有时会返回65535

我有一个函数,它使用difftime来检测自通信心跳停止以来的秒数。 此function可以每50毫秒运行一次。 该函数似乎工作,除了偶尔它返回65535.我可以将执行减少到每秒一次,因为difftime的返回仅在几秒钟内。 但我不知道它是否能解决这个问题。 是不是问题,因为我没有正确地将difftime从double返回到uint16_t?

该程序在ubuntu 64位机器上运行。

请帮忙。 谢谢。

uint16_t commlost(uint16_t heartbeat_read_cur) { time_t current_time; static time_t previous_time; static uint16_t commlost_secs_cur = 0; static uint16_t commlost_secs_prev = 0; static uint16_t heartbeat_read_prev = 0; static bool first_time = TRUE; if (first_time) { previous_time = time(NULL); first_time = FALSE; } time(&current_time); commlost_secs_prev = commlost_secs_cur; if(heartbeat_read_prev == heartbeat_read_cur) { commlost_secs_cur += difftime(current_time, previous_time); } else { heartbeat_read_prev = heartbeat_read_cur; commlost_secs_cur = 0; } previous_time = current_time; return (commlost_secs_cur); } 

difftime()适用于系统,其中time_t支持的时间分辨率高于整数秒。 虽然允许,但我从未遇到过这样的系统 – 我不认为有一个系统存在。 具体来说,在POSIX系统上, time_t以积分秒为单位测量,而difftime()相当于其参数的算术减法,所以实际上你最好只使用:

 commlost_secs_cur += current_time - previous_time ; 

也就是说,你的实现有点过于复杂,而不是累积自上一次调用以来的时间,这可能小于时钟分辨率,你可以简单地记录观察到的最后一次心跳并从那时起返回时间:

 int commlost(uint16_t heartbeat_read_cur) { time_t current_time = time(0) ; static time_t heartbeat_timestamp = 0 ; static uint16_t heartbeat_read_prev ; // If first time, or heartbeat changed... if( heartbeat_timestamp == 0 || heartbeat_read_prev != heartbeat_read_cur) { // ... timestamp heartbeat heartbeat_timestamp = time(0) ; // ... keep last heartbeat heartbeat_read_prev = heartbeat_read_cur ; } // Return seconds since last heartbeat timestamp return current_time - heartbeat_timestamp ; } 

我不确定为什么你会使用uint16_t ; 除非与某些特定协议或文件格式兼容,否则几乎没有优势。

在查询时间之前,请阅读时间(7)手册页(并再次阅读)。

我建议将clock_gettime(2)与例如CLOCK_MONOTONICCLOCK_REALTIME使用,并且最好使用double进行时间计算(因为struct timespec通常大于任何整数类型)。

不要使用uint16_t进行此类时间计算。

尝试使用

 inline double double_gettime (clockid_t cid) { struct timespec ts = {0,0}; clock_gettime(cid, &ts); return (double)ts.tv_sec + 1.0e-9*ts.tv_nsec; } 

您可能希望通过测试clock_gettime是否失败并在失败时提供NAN来使该function更加clock_gettime 这留给读者练习。 对于CLOCK_REALTIME等,您还可以测量进程开始时的某些时间与当前时间之间的差异 (即计算差异的struct timespec并将该差异转换为double

然后就像

 double tstart = double_gettime(CLOCK_REALTIME); some_long_computation(); double tend = double_gettime(CLOCK_REALTIME); printf ("needed %f seconds to compute\n", tend-tstart); 

另见时钟(3)