C中else块与if块的关联

o75abkj4  于 2023-04-19  发布在  其他
关注(0)|答案(5)|浏览(475)

我有一个代码片段,如下所示。有人能解释一下为什么else块与嵌套的if块相关联吗?下面的代码片段的输出是1。我执行了代码,但不明白为什么块以下面的顺序相关联。
更新:这是我在一家公司前一年的面试问题中发现的一个问题。我总是用括号括住我的ifelse块。我现在明白为什么整个块都没有被执行。
谢谢大家的回复:)

int x=1, y=1;
if (y<0)
    if (y>0) x=3;
    else x=5;
printf("%d", x);
oaxa6hgo

oaxa6hgo1#

正式的C和C语法没有指定else是如何关联的。选择由语法之外的规则指定。C 20186.8.4.13说:
else与语法所允许的词法上最接近的前面的if相关联。
C
2020(draft N4849)8.5.1 [stmt.if] 1说:
if语句的第二种形式中(包括else的那个),如果第一个子语句也是if语句,那么内部的if语句将包含else部分。[换句话说,在外部if可以具有else之前,else必须与内部if相关联。]
要查看语法没有指定else是如何关联的,我们可以检查C 2018 6.8.4中的形式语法:

  • selection-statement*:

    `if` `(` * 表达式 * `)` * 语句 *
    `if` `(` * 表达式 * `)` * 语句 * `else` * 语句 *
    `switch` `(` * 表达式 * `)` * 语句 *

利用该语法,if(y<0) if(y>0) x=3; else x=5;可以被解析为if(y>0) x=3; else x=5;是一个 statement,其是“if(expression)statementelsestatement”,或者它可以被解析为if(y>0) x=3;是一个 statement,其是if(expression)statement。父if(y>0)将具有没有elseif形式。在后一种情况下,父if(y>0)将具有if … else形式。

5n0oy7gb

5n0oy7gb2#

通过适当的缩进,它变得更加清晰:

int x = 1, y = 1;

    if (y < 0)         // false, so it jumps directly here
        if (y > 0)     //                                |
            x = 3;     //                                |
        else           //                                |
            x = 5;     //                                |
    printf("%d", x);   // <------------------------------+

添加大括号使其更加清晰。下面的代码与原始代码的含义完全相同:

int x = 1, y = 1;

    if (y < 0) {
        if (y > 0) {
            x = 3;
        } else {
            x = 5;
        }
    }
    printf("%d", x);

也就是说,if(condition) <statement> else <statement><statement>可以是单个语句,也可以是{}语句。没有大括号,只有下一个单个语句将有条件地执行。

iecba09b

iecba09b3#

if语句的定义方式如下(为简单起见,我使用C语法)

selection-statement:
    if ( expression ) statement
    if ( expression ) statement else statement

正如您所看到的,没有if部分,else部分不能作为单独的语句存在。
所以,根据定义,这个if语句:

if(y<0) ...

可以重写为:

if(y<0) statement;
  • statement* 可以是任何语句,包括另一个if语句:
if(y<0) if(y>0) x=3; else x=5;

也就是说,else部分属于最近的if部分。
否则,你可以这样写:

if(y<0) 
{ 
    if(y>0) x=3; 
}
else x=5;

在本例中,statement 是包含if语句而不包含else部分的复合语句。

{ 
    if(y>0) x=3; 
}
t9eec4r0

t9eec4r04#

就好像你在要求逻辑解释为什么它们是让我们看看这段代码:

if( condition1 ) 
    if( condition2 ) x = 1;
    else x = 2;
else x = 3;

如果它会像你建议或预期的那样工作,那么注解掉else x = 3;行将使else x = 2;语句神奇地从if( condition2 )跳到if( condition1 ),而else x = 2所属的位置将取决于else x = 3;的存在,这是一个非常糟糕的做法。但是如果你有疑问,请使用{}来表达你需要的清晰和明确的方式:

if( condition1 ) { 
    if( condition2 ) x = 1;
}
else x = 2;
sulc1iza

sulc1iza5#

在C和C++(以及其他几种语言)中,if..else的结合性规则被设计为支持if..else if链,而无需过多的(视觉)嵌套:

if(a) handle_a();
else if(b) handle_b();
else if(c) handle_c();
else handle_other();

实际上是:

if(a) {
    handle_a();
} else {
    if(b) {
        handle_b();
    } else {
        if(c) {
            handle_c();
        } else {
            handle_other();
        }
    }
}

设计一种能让缩进较少的版本正常工作的语法并不太难,只需特殊大小写为else if即可(就像许多其他语言一样,通常通过特殊的elseif关键字),但C更优雅地完成了此行为,通过引入else成为最接近的前一个ifelse的规则。这导致了if(a); if (b); else c();的特定行为。t特别有用或明显,但它使规则保持简单(r)。

相关问题