Ничего плохого не происходит, пока:
Вы вычитаете DWORD
с, вместо того, чтобы сначала конвертировать в какой-либо другой тип.
Ничто, на что вы пытаетесь рассчитывать, не занимает больше 49,7 дней.
Это связано с тем, что арифметическое переполнение без знака четко определено в C, а поведение обтекания делает именно то, что нам нужно.
DWORD t1, t2;
DWORD difference;
t1 = GetTickCount();
DoSomethingTimeConsuming();
t2 = GetTickCount();
t2 - t1
выдаст правильное значение, даже если GetTickCount
обернут. Только не конвертируйте t2
и t1
в какой-либо другой тип (например, int
или double
) перед выполнением вычитания.
Это не будет работать, если язык программирования рассматривает переполнение как ошибку. Это также не будет работать, если DoSomethingTimeConsuming()
занимает больше 49,7 дней. Вы не можете сказать, просто взглянув на t2
и t1
, сколько раз GetTickCount
обернулось, к сожалению.
Давайте начнем с обычного случая, когда в игру не входит перенос:
t1 = 13487231
t2 = 13492843
Здесь t2 - t1 = 5612
, что означает, что операция заняла около пяти секунд.
Теперь рассмотрим операцию, которая занимает короткое время, но где GetTickCount
обернулся:
t1 = 4294967173
t2 = 1111
Операция заняла 1234 мс, но таймер обернулся, и 1111 - 4294967173
является фиктивным значением -4294966062
. Что мы будем делать?
Ну, по модулю 2 32 , результат вычитания тоже оборачивается:
(DWORD)-4294966062 == (DWORD)1234
Наконец, рассмотрим крайний случай, когда операция занимает почти 2 32 миллисекунд, но не совсем:
t1 = 2339189280
t2 = 2339167207
Здесь GetTickCount
обернулся и вернулся туда, где это было.
Теперь t2 - t1
возвращает фиктивное значение 4294945223
. Это потому, что на это фактически ушло время!
В целом:
(base + offset) - base ≡ offset mod 2^32