奇怪的程序和调试器if语句行为

AJG*_*G85 2 c++ debugging mfc if-statement

这是一个完整性检查,因为我失去了我的.

我有一个方法IsCaptured(),它将枚举状态成员与给定值进行比较并返回一个bool.我结合使用鼠标阈值检查来确定是否应该发送拖动开始消息并开始拖动操作.问题是当它不应该被鼠标移动时触发.我添加了跟踪消息,如下所示:

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;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在奇怪的部分,输出:

false
false
Run Code Online (Sandbox Code Playgroud)

该方法是这样实现的,并m_dragState设置为NONE截获按下按钮:

enum { NONE, CAPTURED, DRAGGING };
bool IsCaptured() const { return m_dragState == CAPTURED; }
Run Code Online (Sandbox Code Playgroud)

我试过重建整个解决方案无济于事.我正在运行VS2010 Debug 64位,该程序是一个单线程MFC应用程序.什么$ @#!在这里?

AnT*_*AnT 8

你的输出没什么奇怪的.&&优先级高于||,这就是为什么你的优先级

if (IsCaptured() &&
    abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y)
Run Code Online (Sandbox Code Playgroud)

被解释为

if ((IsCaptured() && abs(delta.x) >= thresh.x) || 
    abs(delta.y) >= thresh.y)
Run Code Online (Sandbox Code Playgroud)

即如果满足abs(delta.y) >= thresh.y条件,那么整个if条件的结果根本不依赖于你IsCaptured().

编译器并不关心您在换行符中"表达"了您的意图.运算符优先级很重要.换行没有.

你显然打算做的是

if (IsCaptured() && 
    (abs(delta.x) >= thresh.x || abs(delta.y) >= thresh.y))
Run Code Online (Sandbox Code Playgroud)

注意在||子表达式的操作数周围放置额外的括号.

  • @ AJG85:`&&`子表达式确实会在`false`上短路.这意味着当`IsCaptured()`是'false`时,不会评估`abs(delta.x)> = thresh.x`.但这就是它的意思.它没有取消进一步的评估(为什么会这样?).由于`&&`子表达式求值为'false`,`||`*不会*短路并继续评估其第二个操作数,即`abs(delta.y)> = thresh.y`. (3认同)