目录
什么是 GetTickCount?
GetTickCount 是一个 Windows API 函数,用来告诉你“从电脑开机到现在过去了多少毫秒”。它就像一个计时器,记录系统运行的时间,单位是毫秒(1 秒 = 1000 毫秒)。
想象你在玩游戏,想知道从游戏开始到现在过了多久,GetTickCount 就能帮你算这个时间。不过它是从系统启动开始计时的,不是从你程序开始。
什么是 GetTickCount64?
GetTickCount64 是 GetTickCount 的升级版,功能一样,也是返回系统运行的毫秒数,但它用 64 位整数表示,能记录更长时间。
-
定义:
ULONGLONG GetTickCount64();
-
返回值:一个 ULONGLONG 类型的值(64 位无符号整数)。
-
特点:不会轻易溢出,支持 Vista 及以上系统。
函数签名
GetTickCount
的作用就是获取(Get)从系统启动以来经过的时间滴答数(Tick Count)
-
Get
:表示获取(获取某个值)。 -
Tick
:指的是时钟滴答(tick),在计算机中,"tick" 代表系统启动后经过的时间单位(通常是毫秒)。 -
Count
:表示数量,即计数的值。
它的定义很简单:
DWORD GetTickCount();
-
没有参数:直接调用就行,不用传东西。
-
返回值:一个 DWORD 类型的值(无符号整数),表示毫秒数。
怎么用它?
我们写个例子,看看系统运行了多久:
#include <windows.h>
int main() {
// 获取当前毫秒数
DWORD ticks = GetTickCount();
// 输出
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
if (screen == INVALID_HANDLE_VALUE) {
return 1;
}
const char* msg = "GetTickCount 返回值是:(见下一行数字)\n";
DWORD written;
WriteConsoleA(screen, msg, strlen(msg), &written, NULL);
const char* note = "(这是个 32 位整数,单位毫秒)\n";
WriteConsoleA(screen, note, strlen(note), &written, NULL);
return 0;
}
运行后,它会告诉你 ticks 是一个 32 位数字,表示开机时间。
用 GetTickCount64
#define _WIN32_WINNT 0x0600 // 支持 Vista 及以上
#include <windows.h>
int main() {
// 获取当前毫秒数
ULONGLONG ticks = GetTickCount64();
// 输出
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
if (screen == INVALID_HANDLE_VALUE) {
return 1;
}
const char* msg = "GetTickCount64 返回值是:(见下一行提示)\n";
DWORD written;
WriteConsoleA(screen, msg, strlen(msg), &written, NULL);
const char* note = "(这是个 64 位整数,单位毫秒)\n";
WriteConsoleA(screen, note, strlen(note), &written, NULL);
return 0;
}
-
运行后,提示 ticks 是一个 64 位数字。
-
需要加 #define _WIN32_WINNT 0x0600,不然老编译器可能不认识 GetTickCount64。
用法
GetTickCount 最常见的是计时:
-
测量时间差:比如计算一段代码跑了多久。
-
控制速度:比如让游戏每秒更新固定的次数。
-
简单计时器:做一个倒计时或等待效果。
测量时间差的例子
我们测一下等待 2 秒花了多少时间:
#include <windows.h>
int main() {
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
if (screen == INVALID_HANDLE_VALUE) {
return 1;
}
// 开始时间
DWORD start = GetTickCount();
// 暂停 2 秒
Sleep(2000); // 暂停 2000 毫秒
// 结束时间
DWORD end = GetTickCount();
// 时间差
DWORD difference = end - start;
// 输出
const char* msg = "暂停了大约 2000 毫秒,实际差值在下一行\n";
DWORD written;
WriteConsoleA(screen, msg, strlen(msg), &written, NULL);
const char* note = "(差值是个 32 位整数,接近 2000)\n";
WriteConsoleA(screen, note, strlen(note), &written, NULL);
return 0;
}
运行结果:
-
Sleep(2000) 暂停 2000 毫秒(2 秒)。
-
difference 差不多是 2000(可能多几毫秒,因为系统调度有误差)。
-
屏幕显示:“等待时间是 2000 毫秒”。
它们有什么区别?
特性 | GetTickCount | GetTickCount64 |
---|---|---|
返回值类型 | DWORD (32 位) | ULONGLONG (64 位) |
最大值 | 4,294,967,295 毫秒(约 49.7 天) | 18,446,744,073,709,551,615 毫秒(约 584,942 年) |
溢出 | 49.7 天后归零 | 几乎不可能溢出 |
支持系统 | 所有 Windows | Windows Vista 及以上 |
精度 | 10-16 毫秒误差 | 10-16 毫秒误差 |
-
GetTickCount:老版本,适合短期计时,但开机超过 49.7 天会溢出。
-
GetTickCount64:新版本,推荐使用,除非你需要支持 XP。
跟其他计时方式对比
-
std::chrono(C++11):
-
更现代、精确,但需要 C++11 支持。
-
比如 std::chrono::steady_clock。
-
-
GetTickCount:
-
简单粗暴,不需要额外头文件。
-
但精度不高(通常 10-16 毫秒误差)。
-
如果是简单计时,GetTickCount 够用了;如果要超高精度,可以用 GetTickCount64 或 QueryPerformanceCounter。
注意事项
-
范围限制:
-
DWORD 是 32 位无符号整数,最大值是 4,294,967,295 毫秒(约 49.7 天)。
-
如果系统运行超过 49.7 天,GetTickCount 会溢出,从 0 开始重新计数。
-
解决办法:用 GetTickCount64(返回 64 位整数,不会溢出)。
-
-
精度:
-
误差在 10-16 毫秒,不适合超精确计时。
-
-
时间差计算:
-
如果溢出发生在 start 和 end 之间,end - start 会出错。要小心处理。
-
处理溢出的例子
DWORD difference;
if (end >= start) {
difference = end - start;
} else {
difference = (0xFFFFFFFF - start) + end + 1; // 处理溢出
}
更有趣的例子
我们做一个闪烁文字的效果:
#include <windows.h>
#include <cstring>
int main() {
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
if (screen == INVALID_HANDLE_VALUE) {
return 1;
}
const char* message = "闪烁!";
DWORD written;
for (int i = 0; i < 5; i++) {
// 显示红字
SetConsoleTextAttribute(screen, FOREGROUND_RED);
WriteConsoleA(screen, message, strlen(message), &written, NULL);
// 等待 500 毫秒
DWORD start = GetTickCount();
while (GetTickCount() - start < 500) {}
// 清屏
system("cls");
// 等待 500 毫秒
start = GetTickCount();
while (GetTickCount() - start < 500) {}
}
return 0;
}
运行结果:
-
“闪烁!” 在屏幕上红字显示 0.5 秒,然后消失 0.5 秒,循环 5 次。