【问题标题】:How are if and else treated without brackets? [duplicate]如果没有括号如何处理 if 和 else? [复制]
【发布时间】:2020-03-20 17:09:04
【问题描述】:

为什么我运行它时看不到任何显示?我期待 EINVAL 被打印出来,而不是什么都没有。

#include <stdio.h>

unsigned int set_request(int val)
{
    printf("set_request entry\n");
    return 0;
}


void main()
{
    unsigned int val = 2;

    if (val == 0 || val == 1)
        if (set_request(val))
            printf("EIO\n");
    else
        printf("EINVAL\n");
}
jj@coffy:~/nvmemaster/tmp$ ./a.out
jj@coffy:~/nvmemaster/tmp$

当我添加{} 时,我得到了正确的行为,但我想知道没有{}if 的行为。

或者,如果我将赋值行修改为 0,如下所示,那么我会看到其他奇怪的东西。现在我没想到EINVAL 会被打印出来。

#include <stdio.h>

unsigned int set_request(int val)
{
    printf("set_request entry\n");
    return 0;
}


void main()
{
    unsigned int val = 0;

    if (val == 0 || val == 1)
        if (set_request(val))
            printf("EIO\n");
    else
        printf("EINVAL\n");
}
jj@coffy:~/nvmemaster/tmp$ gcc if.c
jj@coffy:~/nvmemaster/tmp$ ./a.out
set_request entry
EINVAL
jj@coffy:~/nvmemaster/tmp$

【问题讨论】:

  • 缩进无关紧要。 C++ 不是 Python。
  • 请阅读What should main() return in C and C++? TL;DR:void main() 不好,您应该使用int main(void)
  • @S.S.Anne 或者甚至更好(在 C++ 中)int main() void 用于空参数列表是 C 主义 - 在 C++ 中不需要。但是是的,void main() 显然是错误的。
  • 这是一种众所周知的语法歧义,大多数语言(包括 C)通过将 else 绑定到最接近的 if 来解决它。这个问题至少可以追溯到 Algol 60。这个问题的计算机科学术语是dangling else

标签: c if-statement


【解决方案1】:

else 将绑定到最里面的if。所以这个:

if (val == 0 || val == 1)
    if (set_request(val))
        printf("EIO\n");
else
    printf("EINVAL\n");

其实是一样的:

if (val == 0 || val == 1) {
    if (set_request(val)) {
        printf("EIO\n");
    } else {
        printf("EINVAL\n");
    }
}

正确绑定else 子句需要大括号。因此,最好始终将它们与if...else 一起使用以避免混淆。

【讨论】:

  • @PaulOgilvie 它显示出等效性。第一个代码块相当于第二个。另请参阅“当我添加{} 时,我得到了正确的行为,但我想知道如果没有{} 的行为” 在问题中。
【解决方案2】:

您的代码如下所示

    if (val == 0 || val == 1)
        if (set_request(val))
            printf("EIO\n");
    else
        printf("EINVAL\n");

现在缩进对编译器来说并不重要,所以它会像这样放置大括号

    if (val == 0 || val == 1)
    {
       if (set_request(val))
            printf("EIO\n");
       else
            printf("EINVAL\n");
    }

所以else不匹配第一个if,而是第二个。

看来你确实想要类似的东西

    if (val == 0 || val == 1)
    {
       if (set_request(val))
            printf("EIO\n");
    }
    else
       printf("EINVAL\n");

在这种情况下,您需要指定大括号。请注意,为避免这种歧义,最好始终使用大括号明确。

此外,如果您在编译时打开警告,编译器将警告您的代码 sn-p。 [-Wdangling-else]

【讨论】:

    【解决方案3】:

    else 与前面最接近的 if 语句匹配。这种情况有一个名字,它是dangling else problem。您的代码实际上被编译器视为:

    void main()
    {
        unsigned int val = 0;
    
        if (val == 0 || val == 1)
            if (set_request(val))
                printf("EIO\n");
            else
                printf("EINVAL\n");
    }
    

    这就是为什么你必须使用花括号来明确你的意图。如果您希望将else 绑定到外部if,您可以将代码编写为:

    void main()
    {
        unsigned int val = 0;
    
        if (val == 0 || val == 1) {
            if (set_request(val))
                printf("EIO\n");
        } else
            printf("EINVAL\n");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-11
      • 1970-01-01
      • 2012-02-02
      相关资源
      最近更新 更多