开发者

Strange program and debugger if statement behavior

开发者 https://www.devze.com 2023-04-07 11:53 出处:网络
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

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_开发者_StackOverflowdragState 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?


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.


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.


You should probably make sure first that the two false's do not refer both to the first trace line.

If the second trace line is actually printing false here, you probably have a classic race condition on your hands and need to protect against it.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号