可能重复:
无意中使用=而不是==
C ++编译器通过您编写的警告让您知道
if( a = b ) { //...
并且这可能是一个错误,你当然想写
if( a == b ) { //...
但有没有一种情况应该忽略警告,因为这是使用这个“function”的好方法? 我没有看到任何代码清晰度可能的原因,那么它有用吗?
两个可能的原因:
while ( (line = readNextLine()) != EOF) { processLine(); }
您可以用来测试函数是否返回任何错误
if (error_no = some_function(...)) { //handle error }
假设some_function在发生错误时返回错误代码,否则返回零
这是C语言基本function的结果:
赋值操作的值是赋值本身 。
您可以将“返回值”用作if()
语句的条件这一事实是偶然的。
顺便说一句,这是同样的技巧,允许这种疯狂的简洁:
void strcpy(char *s, char *t) { while( *s++ = *t++ ); }
当然,当达到t
的nullchar时,while会退出,但同时会将其复制到目标s
字符串。
这是否是一个好主意,通常不是,因为它降低了代码的可读性并且容易出错。
虽然构造是完全合法的语法,您的意图可能真的如下所示:
if( (a = b) != 0 ) { ... }
不要将“!= 0”部分留下。
6个月,1年,5年后看代码的人乍一看,只是相信代码包含一个由jr写的“经典bug”。 程序员并将尝试“修复”它。 CLEARLY上面的结构表明了你的意图,并将由编译器进行优化。 如果你是那个人,这将特别令人尴尬。
你的另一个选择是重复评论。 但以上是自我记录的代码,这是更好的。
最后,我的偏好是这样做:
a = b; if( a != 0 ) { ... }
这很清楚,因为代码可以获得。 如果性能受到影响,则几乎为零。
void some( int b ) { int a = 0; if( a = b ) { // or do something with a // knowing that is not 0 } // b remains the same }
直接回答这个问题,作为一个个人观点,我真的不认为这是一个好主意的情况。
我的意思是,我知道使用这种语法可以避免在代码中添加额外的行,但我认为它会从代码中消除一些可读性。
这种语法对于像@Steven Schlansker建议的那样非常有用,但直接使用它作为条件并不是一个好主意。
只是我的两分钱……
这实际上不是C的故意特征,而是另外两个特征的结果:
赋值返回指定的值
这对于执行多个赋值(例如a = b = 0
)或循环(例如while ((n = getchar()) != EOF)
非常有用。
数字和指针都有真值
C最初在1999年标准之前没有bool
类型,因此它使用int
来表示布尔值。 向后兼容性要求C和C ++允许if
, while
和for
非bool
表达式。
因此,如果a = b
有一个值,并且if
对它接受的值if
宽松,则if (a = b)
有效。 但我建议使用if ((a = b) != 0)
来阻止任何人“修复”它。
一个有用的常见例子可能是:
do { ... } while (current = current->next);
您应该以更好的编码方式明确地编写检查语句,避免使用assign&check方法。 例:
if ((fp = fopen("filename.txt", "wt")) != NULL) { // do something with fp }
while( (l = getline()) != EOF){ printf("%sn", l); }
这当然是最简单的例子,有很多次这是有用的。 要记住的主要事情是(a = true)返回true,就像(a = false)返回false一样。
但有没有一种情况应该忽略警告,因为这是使用这个“function”的好方法? 我没有看到任何代码清晰度可能的原因,那么它有用吗?
可以通过在作业周围放置额外的括号来抑制警告。 这样澄清了程序员的意图。 我见过的常见情况与(a = b)情况直接匹配的情况如下:
if ( (a = expression_with_zero_for_failure) ) { // do something with 'a' to avoid having to reevaluate // 'expression_with_zero_for_failure' (might be a function call, eg) } else if ( (a = expression2_with_zero_for_failure) ) { // do something with 'a' to avoid having to reevaluate // 'expression2_with_zero_for_failure' } // etc.
至于编写这种代码是否足够有用来certificate初学者(有时甚至是最糟糕时刻的专业人士)在使用C ++时遇到的常见错误,很难说。 这是inheritance自C和Stroustrup的遗产,其他有助于设计C ++的人可能已经走了一条完全不同的,更安全的路线,如果他们没有尽可能地使C ++向后兼容C语言。
我个人认为这不值得。 我在一个团队工作,之前我曾多次遇到过这个bug。 我会赞成不允许它(至少需要括号或其他一些明确的语法,否则它被认为是构建错误)以换取减轻遇到这些错误的负担。
前言
请注意,这个答案是关于C ++的(我在添加标签“C”之前开始写这个答案)。
在阅读Jens Gustedt的评论之后,我意识到这不是我第一次写这样的答案。 事实是,这个问题与另一个问题重复,我给出了以下答案:
无意中使用=而不是==
所以,我会在这里无耻地引用自己来添加一个重要的信息: if
不是关于比较。 这是关于评估。
这种差异非常重要,因为它意味着任何东西都可以在if
的括号内,只要它可以被计算为布尔值。 这是件好事。
现在,通过禁止=
限制语言,其中所有其他运算符都被授权,对于该语言来说是一个危险的例外,这个例子的使用远非确定,其缺点确实很多。
对于那些对=
typo不感兴趣的人,那么有解决方案(参见下面的替代方案 ……)。
关于if(i = 0)的有效用法[引自我自己]
问题是你正在把问题颠倒过来。 “if”表示法不是像在某些其他语言中那样比较两个值。
C / C ++ if
指令等待任何将计算为boolean或null / non-null值的表达式。 该表达式可以包括两个值比较,和/或可以更复杂。
例如,您可以:
if(i >> 3) { std::cout << "i is less than 8" << std::endl }
这certificate,在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(p_p)) { // this is a node } else if(SpanNode * p = dynamic_cast(p_p)) { // this is a node } else if(DivNode * p = dynamic_cast(p_p)) { // this is a node } // etc. }
当然,RTTI不应该被滥用,但这只是这种语法糖的一个例子。
另一种用途是使用所谓的C ++ Variable Injection。 在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
和a for
。请参阅下面的源代码以获得更正确的实现)。
这是相同的方式,混合注入if
和for
声明,你可以声明一个原始的foreach宏(如果你想要一个工业级的foreach,使用boost)。
关于你的错字问题
您的问题是一个错字,并且有多种方法可以限制代码中的频率。 最重要的是确保左侧操作数是常量。
例如,由于多种原因,此代码将无法编译:
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
,因此,编译器可以保护我免受大多数错误的影响,包括促使您编写此问题的拼写错误。
但有没有一种情况应该忽略警告,因为这是使用这个“function”的好方法? 我没有看到任何代码清晰度可能的原因,那么它有用吗?
结论
如上例所示,您在问题中使用的function有多种有效用途。
自从我使用此function启用的代码注入后,我自己的代码更清晰,更清晰:
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 ; }
通过这种方式,可以保护自己免受拼写错误的影响,而不需要语言限制(这会使语言瘫痪),因为很少发生的错误(即几乎从来没有,就我在代码中记得的那样)
决不!
引用的例外情况不会产生编译器警告。 在编译器生成警告的情况下,这绝不是一个好主意。
还有一个方面没有提到:C不会阻止你做任何不必要的事情。 它并不妨碍你这样做,因为C的工作就是给你足够的绳索来吊死自己。 不要以为它比你聪明。 它很擅长。
RegEx样本
RegEx r; if(((r = new RegEx(“ w *))。IsMatch()){ // ...在这里做点什么 } else if((r = new RegEx(“ d *”))。IsMatch()){ // ...在这里做点什么 }
作为价值测试
int i = 0; if((i = 1)== 1){ // 1等于分配给int值1的i } 其他{ //? }
我最喜欢的是:
if (CComQIPtr a = BaseClassPtr) { ... } else if (CComQIPtr b = BaseClassPtr) { ... }
以上就是c/c++开发分享在哪种情况下,(a = b)是个好主意?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/560790.html