多个条件语句

时间:2013-02-23 20:22:25

标签: c++ c if-statement

我想知道在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) )确实运行没有错误。我不知道为什么以前失败了;如果最初有效,我甚至可能没有提出这个问题。我会把它归结为巫术和集中注意力不集中。

最终,虽然答案已被暗示但未逐字逐句确认,但似乎依赖于短路评估(感谢维基链接!)是一种合法的技术。我很高兴我不必重写任何代码!

4 个答案:

答案 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,左侧部分优先,&&一旦某些东西返回错误就停止。

你可以在右侧放置任何你想要的东西,它不会评估。

请记住,您使用的“无效”表达式具有未定义的行为,如果它有效,则无法知道会发生什么。