code snippet:

void checkcollision()
{
    float x1 = tanks[0].x;
    float y1 = tanks[0].y;
    float x2 = tanks[1].x;
    float y2 = tanks[1].y;
    float dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    float dr = tanks[0].rad+tanks[1].rad;
    if(dist<dr);
    {
        printf("checkcollision read true\n");
        printf("dist: %f, radius+radius: %f\n",dist,dr);
        goback(0); goback(1);
    }
}

output:

checkcollision read true
dist:363.159302, radius+radius:14.142136
goback executed for tank 1
goback executed for tank 2

I just need someone to break down why this might happen. I don't get it. Do conditional operands not work on float?

Dani AI

Generated

The immediate cause is a stray semicolon placed right after the if condition: that semicolon is a null (empty) statement, so the following { ... } block is just a normal compound statement that always runs. correctly spotted that — removing the semicolon will make the if actually control the block. For the formal rule on statements and the null statement in C, see the language reference: C statements (null statement).

To catch this kind of slip automatically, turn on and act on compiler warnings. Modern toolchains will flag suspicious empty bodies; enable -Wall -Wextra and -Wempty-body, and consider -Werror during development so warnings force fixes. Static analysis (clang-tidy) and editor linters will also highlight likely mistakes. See the GCC warning options for the relevant switches: GCC warning options.

About floats: relational operators (<, >) do work with float — the bug here is syntactic, not numeric. That said, equality checks can fail due to rounding; for geometric collision tests it’s common and cheaper to compare squared distances instead of calling sqrt, e.g. compare dx*dx + dy*dy to (r1 + r2)*(r1 + r2). For background on floating-point behavior and precision issues, see: Floating-point arithmetic.

Other practical tips that build on ’s advice: always use braces for conditionals (even single-line bodies), avoid multiple statements on one line, use #ifdef DEBUG or logging macros rather than leaving printf clutter in production, and write small unit tests for collision logic so these mistakes get caught immediately.

Recommended Answers

All 5 Replies

if(dist<dr);
remove semicolon ?
should be or it will do nothing if dist < dr and do nothing on else

    if(dist<dr)
    {
        printf("checkcollision read true\n");
        printf("dist: %f, radius+radius: %f\n",dist,dr);
        goback(0); goback(1);
    }

thank you. Am I the only one who has trouble seeing small problems in walls of text that comprise code? This is depressing.

No, everyone has them, you need to be patient. Cheer up :)
Just always know that this is c language, there is no magic, if something does not work then you can find out why always. Add as much printf as you can to do that..
Like that

void checkcollision()
{
    float x1 = tanks[0].x;
    float y1 = tanks[0].y;
    float x2 = tanks[1].x;
    float y2 = tanks[1].y;
    float dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    float dr = tanks[0].rad+tanks[1].rad;
    printf("dist: %f, radius+radius: %f\n",dist, dr);
    if(1 < 2)
    {
       puts("yes");
    }
    else
    {
       puts("wtf");
    }
    if(dist < dr) ;
    {
        printf("checkcollision read true\n");
        printf("dist: %f, radius+radius: %f\n",dist,dr);
        goback(0); goback(1);
    }
}

thank you. Am I the only one who has trouble seeing small problems in walls of text that comprise code? This is depressing.

Ane we usually guard these with #ifdef DEBUG ... #endif /* DEBUG */ blocks so that you can turn the printf statements off when you are ready for production. Example:

void checkcollision()
{
    float x1 = tanks[0].x;
    float y1 = tanks[0].y;
    float x2 = tanks[1].x;
    float y2 = tanks[1].y;
    float dist = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    float dr = tanks[0].rad+tanks[1].rad;
#ifdef DEBUG
    printf("dist: %f, radius+radius: %f\n",dist, dr);
    if(1 < 2)
    {
       puts("yes");
    }
    else
    {
       puts("wtf");
    }
#endif /* DEBUG */
    if(dist < dr) ;
    {
        printf("checkcollision read true\n");
        printf("dist: %f, radius+radius: %f\n",dist,dr);
        goback(0); goback(1);
    }
}

So, when you have a valid value, yet you don't get the output from inside the if (dist<dr) clause, then you know you need to look there. In any case, this sort of bug is common to beginners. Another one is to have single line contents of a conditional and not use curly-braces, so when you add code later that should be inside the conditional, it doesnt work correctly. Example:

        if(dist < dr) /* Note - no semicolon now */
            goback(0); goback(1);

This will be another bug since the second goback(1) will execute whether or not dist < dr. Rule: ALWAYS brace ALL conditional blocks of code, whether they are one liners or not. First, it is easier to read. Second, adding more code within the conditional will be less likely to result in inadvertant bugs.

One final thing. Do NOT, if at all possible, execute two separate statements on one line as you have above with goback(0); goback(1);. If they are on two lines, then you can tell more easily that you forgot to enclose them in braces, at least for my example. In your case, you DID enclose them - good, but put both statements on one line - bad.

Thanks guys.

Rubberman, that's really smart using #ifdef DEBUG I'm gonna keep that in mind. I did know about the one line execution after if statement without curly braces, thats why I almost always use it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.