当前位置:  开发笔记 > 编程语言 > 正文

无意中使用=而不是==

如何解决《无意中使用=而不是==》经验,为你挑选了8个好方法。

看起来

if (x=y) { .... }

代替

if (x==y) { ... } 

是许多邪恶的根源.

为什么并非所有编译器都将其标记为错误而不是可配置警告?

我有兴趣找出构造if (x=y)有用的案例.



1> lImbus..:

一个有用的构造是例如:

char *pBuffer;
if (pBuffer = malloc(100))
{
    //continue to work here
}

编辑:
如前所述,现在已经多次投票,我可能会补充说这不是特别好的风格,但经常看到它说它很有用.我也见过这个new,但它让我的胸部更加疼痛.

另一个例子,争议较少,可能是:

while (pointer = getNextElement(context))
{
    //go for it, use the pointer to the new segment of data
}

这意味着当没有下一个元素时函数getNextElement()返回NULL,以便退出循环.


@llmbus:现在malloc失败的日子通常需要请求一大块ram,我不认为printf需要任何接近"巨大"的地方

2> Leeor..:

大多数时候,编译器都非常努力地保持向后兼容.

改变他们在这个问题上的行为以抛出错误将破坏现有的合法代码,甚至开始抛出警告将导致自动系统出现问题,通过自动编译并检查错误和警告来跟踪代码.

这是一个邪恶,我们几乎坚持atm,但有办法规避和减少它的危险.

例:

   void *ptr = calloc(1, sizeof(array));
   if (NULL = ptr) {
       // some error
   }

这会导致编译错误.


它不是关于向后兼容性,而是关于正确性,坚持语言的定义方式.将此标记为错误*的C++编译器不再是C++编译器*.

3> Thomas Padro..:

简单答案:赋值操作(如x = y)具有一个值,该值与x中新分配的值相同.您可以直接在比较中使用它,而不是

x = y; if (x) ...

你可以写

if (x = y) ...

写入(和读取)的代码较少,这有时是一件好事,但现在大多数人都认为应该以其他方式编写它以提高可读性.例如这样:

if ((x = y) != 0) ...

这是一个现实的例子.假设你想用malloc分配一些内存,看它是否有效.它可以像这样逐步编写:

p = malloc(4711); if (p != NULL) printf("Ok!");

与NULL的比较是多余的,因此您可以像这样重写它:

p = malloc(4711); if (p) printf("Ok!");

但由于赋值操作具有可以使用的值,因此可以将整个赋值放在if条件中:

if (p = malloc(4711)) printf("Ok!");

这也是一样的,但更简洁.



4> 小智..:

因为它不是非法的(无论如何使用C或C++)并且有时候很有用......

if ( (x = read(blah)) > 0)
{
    // now you know how many bits/bytes/whatever were read
    // and can use that info. Esp. if you know, say 30 bytes
    // are coming but only got 10
}

大多数编译器如果你没有在括号内放置括号,我会喜欢这个问题.



5> paercebal..:

关于if(i = 0)的有效用法

问题是你正在把问题颠倒过来."if"表示法不是像在某些其他语言中那样比较两个值.

C/C++"if"指令等待任何将计算为布尔值或null /非null值的表达式.该表达式可以包括两个值比较,和/或可以更复杂.

例如,您可以:

if(i >> 3)
{
   std::cout << "i is less than 8" << std::endl
}

这证明,在C/C++中,if表达式不限于==和=.任何事都可以,只要它可以被评估为真或假(C++),或零非零(C/C++).

另一个C++有效用途:

if(MyObject * pObject = dynamic_cast(pInterface))
{
   pObject->doSomething() ;
}

这些是if表达式的简单用法(请注意,这也可以在for循环声明行中使用).确实存在更复杂的用途.

关于C++中if(i = 0)的高级用法[引自自己]

在发现此问题的副本后 在哪种情况下,(a = b)是个好主意?我决定用一个额外的奖励来完成这个答案,也就是说,可变注入一个范围,这在C++中是可能的,因为if它将评估它的表达式,包括一个变量声明,而不是限制自己来比较两个操作数,就像它在其他语言:

所以,引用自己:

另一种用途是使用所谓的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和for声明,你可以声明一个原始的foreach宏(如果你想要一个工业级的foreach,使用boost).

请参阅以下文章,了解不那么天真,更完整和更强大的实现:

http://www.drdobbs.com/184401723?pgno=6

http://www.drdobbs.com/184401728

http://www.drdobbs.com/184401752

这种错误真的发生了多少?

很少.事实上,我还没有记住一个,我8年来一直很专业.我猜它发生了,但是在8年后,我确实产生了相当数量的错误.只是这种错误并没有发生,让我在挫折中记住它们.

在C中,由于缓冲区溢出会导致更多错误,例如:

void doSomething(char * p)
{
   strcpy(p, "Hello World, how are you \?\n") ;
}

void doSomethingElse()
{
   char buffer[16] ;
   doSomething(buffer) ;
}

事实上,微软被烧得如此之难,因为他们在Visual C++ 2008中添加了一个警告,因为他们不赞成使用strcpy!

你怎么能避免大多数错误?

对此错误的第一个"保护"是"转向"表达式:由于无法为常量赋值,因此:

if(0 = p) // ERROR : It should have been if(0 == p). WON'T COMPILE !

不会编译.

但我觉得这个解决方案很糟糕,因为它试图隐藏在风格背后应该是一般的编程实践,即:任何不应该改变的变量应该是不变的.

例如,而不是:

void doSomething(char * p)
{
   if(p == NULL) // POSSIBLE TYPO ERROR
      return ;

   size_t length = strlen(p) ;

   if(length == 0) // POSSIBLE TYPO ERROR
      printf("\"%s\" length is %i\n", p, length) ;
   else
      printf("the string is empty\n") ;
}

尝试尽可能多地"变量"变量将使您避免大多数拼写错误,包括那些不在"if"表达式中的错误:

void doSomething(const char * const p) // CONST ADDED HERE
{
   if(p == NULL) // NO TYPO POSSIBLE
      return ;

   const size_t length = strlen(p) ; // CONST ADDED HERE

   if(length == 0) // NO TYPO POSSIBLE
      printf("\"%s\" length is %i\n", p, length) ;
   else
      printf("the string is empty\n") ;
}

当然,它并不总是可能的(因为一些变量需要改变),但我发现我使用的大多数变量都是常量(我一直初始化它们,然后只读它们).

结论

通常,我看到代码使用if(0 == p)表示法,但没有const-notation.

对我来说,就像有一个垃圾桶用于可回收物品,另一个用于不可回收物品,然后在最后,将它们放在同一个容器中.

因此,不要嘲笑一种简单的习惯习惯,希望它能让你的代码变得更好.它不会.尽可能使用语言结构,这意味着,在这种情况下,在可用时使用if(0 == p)表示法,并尽可能使用const关键字.



6> Patrick..:

'if(0 = x)'成语旁边是无用的,因为当双方都是变量('if(x = y)')和大多数(全部?)的时候你应该使用常量变量时​​它没有帮助而不是魔术数字.

另外两个原因我从不使用这个成语,恕我直言,它使代码可读性降低,说实话,我发现单个'='是非常小的罪恶的根源.如果你彻底测试你的代码(显然我们都这样做),这种语法错误很快就会出现.



7> 小智..:

许多编译器会检测到这一点并发出警告,但前提是警报级别设置得足够高.

例如:

 ~> gcc -c -Wall foo.c
foo.c: In function ‘foo’:
foo.c:5: warning: suggest parentheses around assignment used as truth value



8> orip..:

用于迭代的标准C语言:

list_elem* curr;
while ( (curr = next_item(list)) != null ) {
  /* ... */
}

推荐阅读
ERIK又
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有