Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange program and debugger if statement behavior

This is a sanity check because I've lost mine.

I have a method IsCaptured() which compares an enum state member to a given value and returns a bool. I use this in conjunction with a mouse threshold check to determine if a drag begin message should be sent and a drag operation begun. The problem is this is being triggered on mouse move when it shouldn't be. I've added trace messages as follows:

TRACE(L"%s\n", (IsCaptured()) ? L"true" : L"false");
CPoint delta = pt - m_trackMouse;
static CPoint thresh(GetSystemMetrics(SM_CXDRAG), GetSystemMetrics(SM_CYDRAG));

if (IsCaptured() &&
    abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)
{
    TRACE(L"%s\n", (IsCaptured()) ? L"true" : L"false");
    // Send message to enter drag mode
    bool bDrag = ::SendMessage(m_trackWnd, WM_DD_BEGIN, ::GetDlgCtrlID(m_trackWnd), (LPARAM)(void*)&m_info) != 0;

    // ...
}

Now the strange part, the output:

false
false

The method is implemented like so and m_dragState is set to NONE until there is a button down intercepted:

enum { NONE, CAPTURED, DRAGGING };
bool IsCaptured() const { return m_dragState == CAPTURED; }

I've tried rebuilding the entire solution to no avail. I'm running VS2010 Debug 64-bit and the program is a single threaded MFC app. What the $@#! is going on here?

like image 385
AJG85 Avatar asked Jan 17 '26 20:01

AJG85


2 Answers

There's nothing strange in your output. && has higher precedence than ||, which is why your

if (IsCaptured() &&
    abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)

is interpreted as

if ((IsCaptured() && abs(delta.x) >= thresh.x) || 
    abs(delta.y) >= thresh.y)

I.e. if the abs(delta.y) >= thresh.y condition is met, then the result of the entire if condition does not depend on your IsCaptured() at all.

The compiler does not care that you "expressed" your intent in line breaks. Operator precedence matters. Line breaks don't.

What you apparently were intending to do was

if (IsCaptured() && 
    (abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y))

Note the placement of extra braces around the operands of || subexpression.

like image 82
AnT Avatar answered Jan 20 '26 11:01

AnT


Think of this as:

(IsCaptured() && abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)

this:

 (false && true) || true

Your IsCaptured() doesn't have to be true to progress, so it can quite possibly be false in both printouts.

like image 21
John Humphreys Avatar answered Jan 20 '26 11:01

John Humphreys