使用参数定义宏时,“ else”没有先前的“ if”错误

Huz*_*uzo 3 c nested-if

考虑下面的C代码。

#include <stdio.h>
#define foo(x) if (x>0) printf("Ouch\n");

int main()
{
    int a = 4;
    int b = -3;

    if(a>b)
        foo(b) ;
    else
        printf("Arrg!\n");
    printf("thanks\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序运行时,出现错误提示error: ‘else’ without a previous ‘if’。当我们更换foo(b)if (b>0) printf("Ouch\n")根据宏定义,不应该将程序转移到下面的代码时,用大括号写的?

if(a>b){
    if(x>0){
        printf("Ouch\n");
    }
}
else{
    printf("Arrh!\n");
}
printf("thanks\n");    
Run Code Online (Sandbox Code Playgroud)

我不明白为什么编译器会抱怨。该程序实际上转移到了什么?

谢谢

Bla*_*aze 7

不,这是下面的代码:

if (a > b)
        if (b > 0) printf("Ouch\n");;
    else
        printf("Arrg!\n");
Run Code Online (Sandbox Code Playgroud)

请注意,之后有两个分号("Ouch\n")。这就是破坏代码的原因。在else遵循第二个分号是一个空语句,而不是if之前的语句。原因是您在宏定义中有一个分号,而在宏中又有一个分号。

我建议将类似函数的宏的语句放在其自己的块中,如该答案所示。但这是一般性的建议,在此特定示例中,最好根本没有宏。


PSk*_*cik 5

问题是您的宏扩展到

if(a>b)
    if (b>0) printf("Ouch\n"); ; 
else 
    printf("Arrg!\n");
//...
Run Code Online (Sandbox Code Playgroud)

else因为多余的钱,这不能用;。(也可以在x参数(#define foo(x) if ((x)>0) printf("Ouch\n"))后面加上括号)。

如果您;从宏中丢失了,则将获得不同的解析:else它将与内部匹配,if如下所示:

if(a>b){ /*braces inserted to show the interpretation*/
    if (b>0) printf("Ouch\n");
    else printf("Arrg!\n");
}
Run Code Online (Sandbox Code Playgroud)

并且当您可以通过悬空使宏解决问题时 else

#define foo(x) if ((x)>0) printf("Ouch\n"); else
//a ; after the macro else would complete the `else` with an empty branch
Run Code Online (Sandbox Code Playgroud)

使用此方法,尤其是在其他方法中使用if- else在诸如gcc/的clang编译器-Wall和类似选项时触发警告,因此最好的处理方法是使用惯用语

#define macro() do{/*macro_body*/}while(0)
Run Code Online (Sandbox Code Playgroud)

就你而言

#define foo(x) do{ if ((x)>0) printf("Ouch\n"); }while(0)
Run Code Online (Sandbox Code Playgroud)

有些人喜欢总是将复合语句(由括起来{ })与if/ else语句一起使用,尽管这也可以解决问题,但我觉得如果您制作了函数式宏供其他人使用,则最好不要在其上施加样式。