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_开发者_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.
精彩评论