65.9K
CodeProject 正在变化。 阅读更多。
Home

用于 switch 语句的便捷调试宏

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.55/5 (9投票s)

1999年11月27日

2分钟阅读

viewsIcon

68559

一个宏,用于在你无法到达的地方发生时发出警报

在编写 switch 语句时,你的代码通常会处理 switch 控制变量可能采取的每种情况。例如,如果你有一个 MFC 对话框,其中包含一个组合框或单选按钮组,并且有一个整数成员变量连接到该组合框或单选按钮组,以保存用户的选择,你可能会有一个 switch 语句,该语句根据该变量的值采取操作。

对于像上述示例这样的 switch 语句,你通常知道在正常情况下,代码永远不会到达 switch 语句中的 default 部分。如果代码应该命中 default 部分,则表明 switch 语句或 UI 处理代码中存在错误。断言就是用来捕获这类情况的——即如果代码正常工作,则不应发生的情况。

我创建了这个调试宏,我富有想象力地将其命名为 DEFAULT_UNREACHABLE,你可以将其放在 switch 语句的末尾,以确保任何引入导致执行绕过未处理的 switch 语句的错误都被捕获。该宏通过生成断言失败来让你知道有问题。

  • 调试版本:强制断言失败,以便 MSVC 会直接在出现错误的位置将你转到调试器中。
  • VC 6 及更高版本的发布版本:包含一个 __assume 语句,作为对编译器的优化提示。根据 VC 文档,这会减小 switch 语句的编译代码大小。
  • VC 5 及更早版本的发布版本:不执行任何操作。

你可能会想知道,“为什么发布版本不执行任何操作?最终结果与没有宏的情况相同吗?” 这确实是真的,但请记住,调试版本才是这里的主力。当你测试你的调试版本时,你将捕获并修复由宏标记的错误,确保代码永远不会到达 default 部分。这意味着发布版本不需要在 default 部分包含任何代码,因为(与我一起说)代码永远不会到达那里。

废话不多说,以下是宏的代码以及一个显示如何使用它的示例。

#ifdef _DEBUG
#define DEFAULT_UNREACHABLE default: ASSERT(0); break
#elif _MSC_VER >= 1200
#define DEFAULT_UNREACHABLE default: __assume(0); break
#else
#define DEFAULT_UNREACHABLE default: break
#endif;

示例用法:想象一个带有用于选择星期几的单选按钮的对话框。有一个变量 m_nDay 连接到这些单选按钮。

void CMyDialog::OnOK()
{
    UpdateData();

    switch ( m_nDay )
        {
        case 0: case 6:
            // do something for the weekend...
        break;

        case 1: case 2: case 3:
            // something else for Mon-Wed...
        break;

        case 4: case 5:
            // and something else for Thu-Fri
        break;

        DEFAULT_UNREACHABLE;
        }

作为代码的作者,我知道 m_nDay 不应该包含除 0 到 6 之外的任何值,如果它确实包含,则表明存在错误。因此,我在 switch 语句中放置了 DEFAULT_UNREACHABLE 宏,如果发生这种情况,它会提醒我。

最后需要说明的是,最新的winnt.hSDK 中的文件包含一个 DEFAULT_UNREACHABLE 宏,但它不如这里的宏好。SDK 版本只是简化为 __assume 语句,并且没有提供任何帮助进行调试的机制。

© . All rights reserved.