序言
请注意,这个答案是关于 C++ 的(我在添加标签“C”之前就开始写这个答案了)。
不过,在阅读 Jens Gustedt 的评论后,我意识到这不是我第一次写这种答案。事实是,这个问题与另一个问题重复,我给出了以下答案:
Inadvertent use of = instead of ==
所以,我会在这里无耻地引用自己来添加一个重要信息:if 不是为了比较。这是关于评估的。
这种区别非常重要,因为它意味着任何东西都可以在if 的括号内,只要它可以被评估为布尔值。 这是一件好事。
现在,通过禁止 = 来限制语言,所有其他运算符都被授权,这是该语言的一个危险例外,它的使用远非确定,其缺点确实很多。
对于那些对= 错字感到不安的人,有一些解决方案(请参阅下面的替代方法...)。
问题是你把问题颠倒了。 “if”表示法不是像在其他一些语言中那样比较两个值。
C/C++ if 指令等待任何将评估为布尔值或空/非空值的表达式。此表达式可以包含两个值的比较,和/或可以更复杂。
例如,您可以:
if(i >> 3)
{
std::cout << "i is less than 8" << std::endl
}
这证明了,在C/C++中,if表达式不限于==和=。任何事情都可以,只要它可以被评估为真或假 (C++),或零非零 (C/C++)。
关于有效用途
回到未引用的答案。
以下符号:
if(MyObject * p = findMyObject())
{
// uses p
}
允许用户在 if 中声明然后使用 p。它是一种语法糖……但很有趣。例如,想象一个 XML DOM 类对象的情况,它的类型在运行时之前是未知的,您需要使用 RTTI:
void foo(Node * p_p)
{
if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
{
// this is a <body> node
}
else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
{
// this is a <span> node
}
else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
{
// this is a <div> node
}
// etc.
}
当然,不应滥用 RTTI,但这只是这种语法糖的一个例子。
另一个用途是使用所谓的 C++ 变量注入。在 Java 中,有一个很酷的关键字:
synchronized(p)
{
// Now, the Java code is synchronized using p as a mutex
}
在 C++ 中,您也可以这样做。我没有记住确切的代码(也没有我发现它的确切 DDJ 文章),但这个简单的定义应该足以用于演示目的:
#define synchronized(lock) \
if (auto_lock lock_##__LINE__(lock))
synchronized(p)
{
// Now, the C++ code is synchronized using p as a mutex
}
(请注意,此宏非常原始,不应按原样在生产代码中使用。真正的宏使用if 和for。有关更多信息,请参阅下面的来源正确的实现)。
同样的方法,将注入与if 和for 声明混合,您可以声明一个原始的foreach 宏(如果您想要一个工业强度的foreach,请使用boost's)。
关于您的错字问题
您的问题是错字,有多种方法可以限制其在代码中出现的频率。最重要的是确保左侧操作数是常量。
例如,由于多种原因,这段代码无法编译:
if( NULL = b ) // won't compile because it is illegal
// to assign a value to r-values.
甚至更好:
const T a ;
// etc.
if( a = b ) // Won't compile because it is illegal
// to modify a constant object
这就是为什么在我的代码中,const 是您会发现的最常用的关键字之一。除非我真的想修改一个变量,否则它会被声明为 const,因此编译器可以保护我免受大多数错误的影响,包括促使您编写此问题的拼写错误。
但是是否存在应该忽略警告的情况,因为它是使用此“功能”的好方法?我看不出任何代码清晰的原因,所以它是否有用?
结论
如上面的示例所示,您在问题中使用的功能有多种有效用途。
由于我使用了此功能启用的代码注入,因此我自己的代码更加清晰和清晰:
void foo()
{
// some code
LOCK(mutex)
{
// some code protected by a mutex
}
FOREACH(char c, MyVectorOfChar)
{
// using c
}
}
...这使得我很少遇到这种错字所付出的代价可以忽略不计(而且我不记得我上次写这种类型时没有被编译器发现是什么时候)。
有趣的来源
我终于找到了我读过的关于变量注入的文章。来了!!!
替代方案
如果有人担心成为=/== 错字的受害者,那么使用宏可能会有所帮助:
#define EQUALS ==
#define ARE_EQUALS(lhs,rhs) (lhs == rhs)
int main(int argc, char* argv[])
{
int a = 25 ;
double b = 25 ;
if(a EQUALS b)
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
if(ARE_EQUALS(a, b))
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
return 0 ;
}
这样,人们可以保护自己免受拼写错误的影响,而不需要语言限制(这会削弱语言),因为这是一个很少发生的错误(即几乎从不,据我在我的代码中记得它)