我使用下面的代码在“发布”中断言,有一段时间没有出现任何问题。 然后出现了 Visual Studio 2010 Pro SP1,事情变得很糟糕,as also happened to mr. Krunthar .
问题是,当我有一段代码在其中进行完整性检查时:
#define ASSERT(condition, msg) do { (void)sizeof(condition); } while (0,0)
// Note: (0,0) is to avoid warning C4127: conditional expression is constant
{
int result = CallMeOnce(); // its side effects are the important stuff
// perform additional sanity checks in debug
ASSERT(result >= 0, "too low");
ASSERT(result <= 100, "too high");
ASSERT(!isPrime(result), "too prime");
}
VS2010 发出 warning C4189: 'result' : local variable is initialized but not referenced
我不知道如何解决这个问题:
(void)(condition)
之类的代码将执行作为条件传递的任何表达式,这是一个 no no- 不可能将
CallMeOnce()
放在 ASSERT 表达式中 - 重构所有不同的
CallMeOnce()
不是一种选择 - 我宁愿不必编写像
(void)result
、if (result == result) {}
或UNREFERENCED_PARAMETER(result) 这样的脚手架代码
(或等价物)在宏之外只是为了避免警告,因为它使代码更难阅读(污染),并且在 Debug 中编写代码时很容易忘记。还有:在很多地方!
我正在考虑为变量创建另一个宏(ASSERTU?),但感觉太……古怪了!
有没有人找到更好的出路?
非常感谢!
编辑:阐明了调用者级别变量处理的偏好
最佳答案
在你的断言宏中你有
(void)sizeof(condition);
估计这段代码是别人写的,所以,解释一下:
(void)
转换的作用是告诉编译器您确实打算让这个什么也不做的表达式语句什么都不做。
现在对你的结果
做同样的事情
这很容易,不是吗?有时解决方案只是盯着你看。 ;-)
顺便说一句,当这个构造用于抑制关于未使用的形式参数的警告时,您可能想要添加名称的重新定义,例如
(void) unusedArg; struct unusedArg;
这可以防止在以后维护代码时无意中使用参数
然而,visual c++ 生成的错误并不完全是信息性的
可以添加无数级别的复杂性,但我认为即使是名称重新定义也可能太过分了——成本可能大于优势
关于c++ - Visual Studio 2010 SP1 中的断言和未使用的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15819292/