C语言gettickcount如何获取精确时间?

99ANYc3cd6
预计阅读时长 15 分钟
位置: 首页 C语言 正文

GetTickCount 是一个在 Windows 操作系统上非常常用的 API 函数,用于获取自系统启动以来经过的毫秒数,它简单、高效,非常适合用于测量短时间间隔、实现简单的延时功能或计算程序运行时间。


函数原型

GetTickCount 在 Windows SDK 中的定义如下:

DWORD GetTickCount(void);
  • 返回值类型: DWORD,这是一个 32 位无符号整数,其范围是 0 到 4,294,967,295 (即 2^32 - 1)。
  • 单位: 毫秒。
  • 含义: 返回从 Windows 操作系统启动到当前时刻所经过的毫秒数。

工作原理与精度

GetTickCount 的值是从系统启动时开始累加的,通常由系统的硬件定时器(如 PIT - Programmable Interval Timer)驱动。

重要特性:

  • 非高精度: 它的精度通常在 10 到 16 毫秒左右,具体取决于 Windows 的系统定时器间隔(timer resolution),它不适合用于需要微秒级精度测量的场景。
  • 会回绕: 由于 DWORD 是 32 位,它的最大值是 4,294,967,295 毫秒,换算成大约是 7 天,当系统运行时间超过这个值后,GetTickCount 的值会从 0 重新开始计数,这在编写需要长时间运行的程序时是一个必须考虑的因素。

使用示例

示例 1:测量代码执行时间

这是最常见的用法,通过记录代码执行前后的 GetTickCount 值,并计算它们的差值,来获得代码块的执行耗时。

#include <stdio.h>
#include <windows.h> // 必须包含此头文件
int main() {
    // 获取开始时间
    DWORD start_time = GetTickCount();
    // --- 模拟一段需要测量的代码 ---
    Sleep(1000); // 让程序休眠1秒,以便观察
    for (int i = 0; i < 1000000; i++) {
        int a = i * i;
    }
    // -----------------------------
    // 获取结束时间
    DWORD end_time = GetTickCount();
    // 计算耗时(单位:毫秒)
    DWORD elapsed_time = end_time - start_time;
    printf("代码执行耗时: %u 毫秒\n", elapsed_time);
    return 0;
}

编译与运行:

  • 使用 Visual Studio: 直接创建一个 C++ 控制台项目(即使代码是 C 语言,项目类型也无妨),编译运行即可。
  • 使用 MinGW (GCC): 在命令行中运行 gcc your_file_name.c -o your_program.exe,然后执行 your_program.exe

示例 2:处理回绕问题

如果代码可能长时间运行,或者间隔时间可能接近 49.7 天,需要处理回绕问题,一个简单的方法是使用 64 位整数来存储时间戳。

#include <stdio.h>
#include <windows.h>
// 一个更安全的计时函数,可以处理回绕问题
DWORD GetElapsedSafe(DWORD start) {
    DWORD current = GetTickCount();
    // 如果当前时间小于开始时间,说明发生了回绕
    if (current < start) {
        // 回绕后的总时间 = (最大DWORD值 - start时间) + 当前时间
        return (0xFFFFFFFF - start) + current;
    } else {
        // 没有回绕,直接相减
        return current - start;
    }
}
int main() {
    DWORD start_time = GetTickCount();
    // 假设这里有一段运行时间不确定的代码
    Sleep(500); // 模拟运行
    DWORD elapsed_time = GetElapsedSafe(start_time);
    printf("经过的时间: %u 毫秒\n", elapsed_time);
    return 0;
}

GetTickCount vs. 其他计时方法

在 Windows 上,有多种计时方法,选择哪一种取决于你的具体需求(精度、跨平台、范围等)。

函数/方法 精度 范围 跨平台 备注
GetTickCount() ~15ms ~49.7天 仅 Windows 简单、高效,适合短时间间隔和性能分析。
timeGetTime() ~15ms ~49.7天 仅 Windows GetTickCount 类似,但可以通过 timeBeginPeriod 提高精度(会消耗更多CPU资源)。
QueryPerformanceCounter() 微秒级 无限制 仅 Windows 高精度计时的首选,需要配合 QueryPerformanceFrequency() 使用。
clock() (C标准库) 毫秒级 依赖于 CLOCKS_PER_SEC 跨平台 返回的是“进程时间”(CPU时间),而不是“挂钟时间”,不适合测量I/O等待等阻塞时间。
<chrono> (C++11/14/17) 系统最高可用精度 依赖于实现 跨平台 现代C++推荐的方式,类型安全,接口清晰。

替代方案(推荐)

对于现代 C++ 开发,强烈推荐使用 <chrono> 库,它更安全、更灵活,并且是跨平台的。

使用 C++ <chrono> 测量时间

#include <iostream>
#include <chrono> // 包含chrono库
#include <thread> // 包含this_thread::sleep_for
int main() {
    // 获取开始时间点
    auto start = std::chrono::high_resolution_clock::now();
    // --- 模拟一段需要测量的代码 ---
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    for (int i = 0; i < 1000000; i++) {
        int a = i * i;
    }
    // -----------------------------
    // 获取结束时间点
    auto end = std::chrono::high_resolution_clock::now();
    // 计算时间差
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    // 输出结果
    std::cout << "代码执行耗时: " << duration.count() << " 毫秒" << std::endl;
    return 0;
}

为什么推荐 <chrono>

  1. 类型安全: 你操作的是时间点 (time_point) 和时长 (duration) 类型,而不是原始的数字,减少了出错的可能。
  2. 高精度: high_resolution_clock 会自动选择系统可用的最高精度时钟。
  3. 跨平台: 代码可以在 Windows, Linux, macOS 等多种操作系统上编译运行,无需修改。
  4. 易于转换: 可以轻松地在秒、毫秒、微秒、纳秒之间进行转换,std::chrono::duration_cast<std::chrono::microseconds>(duration)

特性 GetTickCount
优点 非常简单易用。
轻量级,调用开销小。
在 Windows 平台上广泛可用。
缺点 精度较低(约15ms)。
存在回绕问题(~49.7天)。
非跨平台,仅限 Windows。
适用场景 - 简单的程序运行时间估算。
- 游戏中的帧率控制或简单延时。
- 不需要高精度的性能分析。
现代替代 对于 C++,优先使用 <chrono>,对于需要更高精度的纯 C Windows 程序,使用 QueryPerformanceCounter
-- 展开阅读全文 --
头像
dede5.7拼音去id怎么实现?
« 上一篇 01-03
C语言inputpicture
下一篇 » 01-03

相关文章

取消
微信二维码
支付宝二维码

目录[+]