这是一个非常经典且在 Linux/Unix 系统中广泛使用的函数,用于获取当前时间,虽然在新代码中推荐使用更现代的 clock_gettime,但 gettimeofday 因其简单性和广泛的历史存在,仍然非常重要。

(图片来源网络,侵删)
函数原型
gettimeofday 函数定义在 <sys/time.h> 头文件中。
#include <sys/time.h> int gettimeofday(struct timeval *tv, struct timezone *tz);
功能描述
gettimeofday 函数用于获取当前日历时间(精确到微秒),它将时间信息存储在 struct timeval 结构体中。
参数详解
函数有两个参数:
a) struct timeval *tv (输入/输出参数)
这是一个指向 timeval 结构体的指针,函数会将获取到的时间信息填充到这个结构体中,如果这个参数是 NULL,则函数不会获取或填充时间信息。

(图片来源网络,侵删)
timeval 结构体的定义如下:
struct timeval {
time_t tv_sec; // 秒 (seconds since Jan. 1, 1970)
suseconds_t tv_usec; // 微秒 (microseconds, 0 to 999,999)
};
tv_sec: 自 Unix 纪元(1970年1月1日00:00:00 UTC)以来经过的秒数。tv_usec: 在当前秒内经过的微秒数(0 到 999,999)。
b) struct timezone *tz (输入/输出参数)
这是一个指向 timezone 结构体的指针,用于获取时区信息,在现代系统中,这个参数几乎总是被忽略,为了可移植性和避免问题,强烈建议将其设置为 NULL。
timezone 结构体的定义如下(在 <sys/time.h> 中):
struct timezone {
int tz_minuteswest; // 格林威治时间以西的分钟数
int tz_dsttime; // 夏令时类型
};
返回值
- 成功时:返回
0。 - 失败时:返回
-1,并设置errno来指示错误原因(EFAULT表示无效的指针地址)。
使用示例
下面是一个完整的示例,展示如何使用 gettimeofday 获取当前时间并将其打印出来。

(图片来源网络,侵删)
#include <stdio.h>
#include <sys/time.h> // 包含 gettimeofday 的头文件
#include <unistd.h> // 包含 sleep 函数的头文件
int main() {
struct timeval start_time, end_time;
// 获取开始时间
if (gettimeofday(&start_time, NULL) != 0) {
perror("gettimeofday (start) failed");
return 1;
}
printf("程序开始运行...\n");
printf("开始时间: 秒 = %ld, 微秒 = %ld\n", start_time.tv_sec, start_time.tv_usec);
// 模拟一些工作,比如休眠1秒
sleep(1);
// 获取结束时间
if (gettimeofday(&end_time, NULL) != 0) {
perror("gettimeofday (end) failed");
return 1;
}
printf("程序结束运行...\n");
printf("结束时间: 秒 = %ld, 微秒 = %ld\n", end_time.tv_sec, end_time.tv_usec);
// 计算耗时
long seconds = end_time.tv_sec - start_time.tv_sec;
long microseconds = end_time.tv_usec - start_time.tv_usec;
// 处理微秒借位
if (microseconds < 0) {
seconds--;
microseconds += 1000000;
}
double elapsed_time = seconds + microseconds / 1000000.0;
printf("程序总耗时: %ld 秒 %ld 微秒\n", seconds, microseconds);
printf("程序总耗时 (秒): %.6f\n", elapsed_time);
return 0;
}
编译和运行
在 Linux 或 macOS 系统上,使用 GCC 编译:
gcc -o time_example time_example.c ./time_example
预期输出
程序开始运行...
开始时间: 秒 = 1678886400, 微秒 = 123456
程序结束运行...
结束时间: 秒 = 1678886401, 微秒 = 125345
程序总耗时: 1 秒 1889 微秒
程序总耗时 (秒): 1.001889
(注意:秒数和微秒数会根据你运行程序的时间而变化)
gettimeofday vs. clock_gettime
虽然 gettimeofday 很好用,但它并不是 POSIX 标准的一部分,而是 BSD 和 Linux 的特定扩展,更重要的是,它已经被标记为过时。
现代 C 编程中,推荐使用 clock_gettime。
clock_gettime 的优势
- POSIX 标准:
clock_gettime是 POSIX.1-2001 标准的一部分,具有更好的可移植性(适用于 Linux, macOS, 以及其他遵循 POSIX 的系统)。 - 更高的精度:
clock_gettime可以提供纳秒级的精度(如果系统支持),而gettimeofday通常是微秒级。 - 更多的时间源:
clock_gettime允许你选择不同类型的时钟源,而不仅仅是日历时间。CLOCK_REALTIME: 类似于gettimeofday,返回系统范围的实时时间。CLOCK_MONOTONIC: 返回一个单调递增的时钟,它不受系统时间调整(如 NTP 同步或用户手动修改时间)的影响。非常适合用于测量耗时。CLOCK_PROCESS_CPUTIME_ID: 测量当前进程消耗的 CPU 时间。CLOCK_THREAD_CPUTIME_ID: 测量当前线程消耗的 CPU 时间。
clock_gettime 示例
下面是使用 clock_gettime 重新实现上面的耗时计算示例:
#define _POSIX_C_SOURCE 199309L // 需要定义这个宏才能使用 clock_gettime
#include <stdio.h>
#include <time.h> // 包含 clock_gettime 的头文件
#include <unistd.h> // 包含 sleep 函数的头文件
int main() {
struct timespec start_time, end_time;
// 使用 CLOCK_MONOTONIC 来测量耗时,因为它不受系统时间变化的影响
if (clock_gettime(CLOCK_MONOTONIC, &start_time) != 0) {
perror("clock_gettime (start) failed");
return 1;
}
printf("程序开始运行...\n");
printf("开始时间: 秒 = %ld, 纳秒 = %ld\n", start_time.tv_sec, start_time.tv_nsec);
sleep(1);
if (clock_gettime(CLOCK_MONOTONIC, &end_time) != 0) {
perror("clock_gettime (end) failed");
return 1;
}
printf("程序结束运行...\n");
printf("结束时间: 秒 = %ld, 纳秒 = %ld\n", end_time.tv_sec, end_time.tv_nsec);
// 计算耗时
long seconds = end_time.tv_sec - start_time.tv_sec;
long nanoseconds = end_time.tv_nsec - start_time.tv_nsec;
// 处理纳秒借位
if (nanoseconds < 0) {
seconds--;
nanoseconds += 1000000000;
}
double elapsed_time = seconds + nanoseconds / 1000000000.0;
printf("程序总耗时: %ld 秒 %ld 纳秒\n", seconds, nanoseconds);
printf("程序总耗时 (秒): %.9f\n", elapsed_time);
return 0;
}
| 特性 | gettimeofday |
clock_gettime |
|---|---|---|
| 头文件 | <sys/time.h> |
<time.h> |
| 标准 | BSD/Linux 扩展,非 POSIX | POSIX.1-2001 及以后 |
| 状态 | 过时 | 推荐 |
| 精度 | 微秒 (µs) | 纳秒 (ns,如果支持) |
| 时间源 | 只有日历时间 (CLOCK_REALTIME 类似) |
多种时钟源 (REALTIME, MONOTONIC, PROCESS_CPUTIME, 等) |
| 可移植性 | 较差 (主要在 Unix-like 系统) | 更好 (POSIX 标准) |
- 对于新项目,请优先使用
clock_gettime,它更标准、更灵活、精度更高。 - 维护旧代码或进行简单的、跨平台要求不高的快速原型开发时,
gettimeofday仍然是一个简单有效的选择。 - 绝对不要用
gettimeofday来测量耗时,因为它会受到系统时间同步的影响,应该使用clock_gettime(CLOCK_MONOTONIC, ...)来测量时间间隔。
