Home > Net >  Compiler ignores my if statement in while(true)
Compiler ignores my if statement in while(true)

Time:09-16

here's my code for sending messages every 3 seconds for 10 times. but it ignores all of if statements in while(true)

double current;
double freq;
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
QueryPerformanceCounter((LARGE_INTEGER*)&current);
float totalTime = 0.f;
float counter = 0.f;
while (true)
{
    double previous = current;
    QueryPerformanceCounter((LARGE_INTEGER*)&current);
    double deltaTime = (current - previous) / freq;
    totalTime  = deltaTime;
    counter  = deltaTime;


    if (counter > 3.f)
    {
        cout << "msg Sent" << totalTime << "\n";
        counter = 0;
    }
    if (totalTime > 30.f)
    {
        break;
    }
}

weird thing is that if I print out two of those values in the middle, it works fine.

double current;
double freq;
QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
QueryPerformanceCounter((LARGE_INTEGER*)&current);
float totalTime = 0.f;
float counter = 0.f;
while (true)
{
    double previous = current;
    QueryPerformanceCounter((LARGE_INTEGER*)&current);
    double deltaTime = (current - previous) / freq;
    totalTime  = deltaTime;
    counter  = deltaTime;

    cout << totalTime << "\n";
    cout << counter << "\n";

    if (counter > 3.f)
    {
        cout << "msg Sent" << totalTime << "\n";
        counter = 0;
    }
    if (totalTime > 30.f)
    {
        break;
    }
}

I think it happened because of compiler optimization. if I'm right, is there any way to stop compiler messing up my code?

LARGE_INTEGER current;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&current);

float totalTime = 0.f;
float counter = 0.f;
while (true)
{
    LARGE_INTEGER previous = current;
    QueryPerformanceCounter(&current);

    double deltaTime = (current.QuadPart - previous.QuadPart) / static_cast<double>(freq.QuadPart);

    totalTime  = deltaTime;
    counter  = deltaTime;

    if (counter > 3.f)
    {
        cout << "msg Sent" << totalTime << "\n";
        counter = 0;
    }
    if (totalTime > 30.f)
    {
        break;
    }
}

This time I followed c rule and the result is same. So it's not the trouble of casting. and it also works when i put two prints in the middle.

CodePudding user response:

It is likely that the problem is due to deltaTime being significantly smaller than 3.f and 30.f.

Since, unless either if branch is taken, the loop body doesn't do anything except measure a clock, the time between iterations is likely to be very small. Initially, this won't be a problem and deltaTime will be correctly added to counter and totalTime. However, as these variables increase in size, they will eventually become so large that deltaTime will fall below the precision provided by double. When this happens, adding deltaTime will cease to increase these variables as the result will round out to exactly the original value.

This is made worse by using float to represent counter and totalTime, which is the floating point type with the lowest precision, meaning the problem will appear for at larger values of deltaTime than if a better floating point type was used.

By adding several std::cout the loop body may be slowed enough that deltaTime is always large enough to be meaningful relative to counter and totalTime.

Instead of counting time using imprecise floating point types, use integer types when possible to avoid this problem. Based on freq you can calculate how many ticks are equivalent to your 3.f and 30.f constants. You can then just count ticks and compare that count to the calculated limits.

  • Related