我想知道在C / C ++中如何处理多种条件。我有一些工作正常的代码,但我担心有一个运气的元素,我不想被抓住。考虑:
if ( (/*condition1*/) || (/*condition containing invalid reference*/) )
{
// do something
}
只要'条件1'为TRUE,即使条件本身会产生错误,第二个条件似乎也不会产生错误。例如:
int main()
{
char string1[] = "StackOverflow";
char *string2 = 0;
// (1) This will work because string1 is valid
if (strlen(string1) != 0)
printf("%s", string1);
// (2) This will cause an error
if (strlen(string2) != 0)
printf("%s", string2);
// (3) But this if(OR) works fine
if ((strlen(string1) != 0)||(strlen(string2) != 0))
printf("no problem!");
// (4) And of course this doesn't
if ((strlen(string2) != 0)||(strlen(string1) != 0))
printf("I don't believe it!");
return 0;
}
可以看到OR条件列表,if()'question'在第一个TRUE语句处停止,从左到右读取,无论如何。但是,将数字(3)更改为:
if ((strlen(string1) == 0) && (strlen(string2) == 0)
尽管第一个条件为假,仍然会失败,从而使整个事情变为假 - 即问题不会像OR示例那样停止。
概括来说,我观察到以下内容:
if ( (TRUE) or (INVALID) ) -> no problem
if ( (FALSE) or (INVALID) ) -> error
if ( (TRUE) and (INVALID) ) -> error
if ( (FALSE) and (INVALID) ) -> error // see the EDIT
这些结果在所有情况下都是通用的,还是依赖于编译器/平台?
我是否可以按照上述规则编写代码,或者我是否应该进入其中一个条件无效的情况?
我正在为我的老板经历一些旧代码,并且上面有如上面的例子(3)。它需要相当长的时间来捕获它们并调整代码以避免任何无效条件。虽然(3)和(4)可以很容易地调整到位于if(string2 != 0) { // }
块内,但实际上对于我的代码来说并不是那么容易。
编辑:
由于再次检查,if ( (FALSE) and (INVALID) )
确实运行没有错误。我不知道为什么以前失败了;如果最初有效,我甚至可能没有提出这个问题。我会把它归结为巫术和集中注意力不集中。
最终,虽然答案已被暗示但未逐字逐句确认,但似乎依赖于短路评估(感谢维基链接!)是一种合法的技术。我很高兴我不必重写任何代码!
答案 0 :(得分:2)
是的,这是众所周知的行为,它适用于遵循标准的任何C / C ++编译器。正如杰西在他的评论中已经提到的那样,这种短路被称为短路,并经常使用指针:
void func( int *ptr )
{
if( ptr && *ptr ) {
// pointer is valid and integer that it points to is not 0
}
}
你的上一个陈述:
if ( (FALSE) and (INVALID) ) -> error
是不正确的。又名&&如果left为false,则不会评估右操作数。
答案 1 :(得分:2)
您所谈论的内容称为“短路”,它是c ++中的通用功能。它的工作方式是(TRUE || anything)总是如此,所以一旦知道它将是真的,表达式就不会被进一步评估。这同样适用(FALSE&& anything),因为这总是错误的。
这是一个很有用的例子:
int x = 0;
cin >> x;
if (x != 0 && 10 / x == 2) {
// ...
}
通过对x进行检查,如果用户输入0,则不会发生10/0,从而使程序除以0。
您可以使用包含&&的表达式来依赖此功能。和||
答案 2 :(得分:0)
if (strlen(string2) != 0)
printf("%s", string2);
此处string2
不是字符串,因此strlen
调用会调用未定义的行为。
if ((strlen(string1) != 0)||(strlen(string2) != 0))
在C中,||
运算符保证在其左操作数求值为1
时不计算其右操作数。在这里,||
的左操作数计算为1
,因此strlen(string2)
(未定义的行为)永远不会被调用。
答案 3 :(得分:0)
在C和C ++中,只要确定结果为||,它就会停止评估布尔表达式因此,运算符总是停止评估,一旦返回true,左侧部分优先,&&一旦某些东西返回错误就停止。
你可以在右侧放置任何你想要的东西,它不会评估。
请记住,您使用的“无效”表达式具有未定义的行为,如果它有效,则无法知道会发生什么。