我正在尝试编写一个较小的库,使我能够度量使用struct timespec时测量的平均时间。因为C不允许操作符重载,所以我不得不构建函数。我知道像end_time < start_time这样的检查是没有完成的,但是为了实现代码中的某种短处,我忽略了它们。计算的准确性是首要目标。
enum { NS_PER_SECOND = 1000000000L };
enum { MAX_NS = 999999999 };
// t1 --> start time
// t2 --> end time
// set t1 and t2 by:
// clock_gettime(CLOCK_REALTIME, &t1);
struct timespec get_timespec_diff(const struct timespec t1, const struct timespec t2)
{
struct timespec t;
t.tv_nsec = t2.tv_nsec - t1.tv_nsec;
t.tv_sec = t2.tv_sec - t1.tv_sec;
if (t.tv_sec > 0 && t.tv_nsec < 0) {
t.tv_nsec += NS_PER_SECOND;
t.tv_sec--;
} else if (t.tv_sec < 0 && t.tv_nsec > 0) {
t.tv_nsec -= NS_PER_SECOND;
t.tv_sec++;
}
return t;
}
struct timespec timespec_add(const struct timespec t1, const struct timespec t2) {
unsigned int total_ns = t1.tv_nsec + t2.tv_nsec;
unsigned int total_s = t1.tv_sec + t2.tv_sec;
while(total_ns > MAX_NS) {
total_ns -= (unsigned)(MAX_NS + 1);
total_s++;
}
struct timespec ret;
ret.tv_sec = total_s;
ret.tv_nsec = total_ns;
return ret;
}
struct timespec timespec_avg(const struct timespec t, const unsigned n) {
struct timespec ret;
ret.tv_sec = 0;
ret.tv_nsec = 0;
unsigned int total_ns = t.tv_nsec + (t.tv_sec * (MAX_NS+1));
unsigned int avg_ns = total_ns/n;
while(avg_ns > MAX_NS) {
ret.tv_sec++;
avg_ns /= 10;
}
ret.tv_nsec = avg_ns;
return ret;
}发布于 2020-11-29 16:00:14
time_t假设,而不是规范OP的代码假设1) time_t是整数类型。可能是浮点。2) unsigned/int不是16位--它们可能是。
正常范围为.tv_sec >= 0和0 <= .tv_nsec <= 999999999。有用的是,代码不太依赖于这一点。
在timespec_add()中,t1.tv_sec + t2.tv_sec可能导致溢出,从而导致未定义的行为。
当unsigned int total_ns = t1.tv_nsec + t2.tv_nsec;是16位时,unsigned很容易无法提供正确的结果--最好使用long.
timespec_avg(const struct timespec t, const unsigned n)看起来更像是一个鸿沟,而不是平均时间。
备选建议:
#include <time.h>
#define NS_PER_SECOND 1000000000
// Averaging without overflow, even if `t1,t2` outside normal range
struct timespec timespec_avg(struct timespec t1, struct timespec t2) {
struct timespec avg;
int remainder = t1.tv_sec % 2 + t2.tv_sec % 2;
avg.tv_sec = t1.tv_sec / 2 + t1.tv_sec / 2;
avg.tv_nsec = t1.tv_nsec / 2 + t1.tv_nsec / 2 + (t1.tv_nsec % 2 + t1.tv_nsec % 2) / 2;
avg.tv_sec += avg.tv_nsec / NS_PER_SECOND;
avg.tv_nsec = avg.tv_nsec % NS_PER_SECOND + (NS_PER_SECOND / 2 * remainder);
if (avg.tv_nsec >= NS_PER_SECOND) {
avg.tv_nsec -= NS_PER_SECOND;
avg.tv_sec++;
} else if (avg.tv_nsec < 0) {
avg.tv_nsec += NS_PER_SECOND;
avg.tv_sec--;
}
return avg;
}https://codereview.stackexchange.com/questions/252762
复制相似问题