解释代码成功编译的原因

时间:2013-03-28 12:33:28

标签: c comments c-preprocessor

通常,如果代码中存在*/ (阻止评论结束)而没有/* (阻止评论开放),编译器产生错误。

但是,为什么编译器 NOT 会在以下情况下产生错误?

#include <stdio.h>
int main(void)
{
    #ifdef abcd
    printf("what ever it is");
    #endif */   --> the problem with this stray '*/' after #endif
    return 0;
}

5 个答案:

答案 0 :(得分:3)

我刚刚用gcc 4.6.x编译了你提供的代码而没有任何标志,并得到了警告

warning: extra tokens at end of #endif directive [enabled by default]

所以预处理器首先删除所有注释,然后跳过#endif行的所有数据。所以我不知道它是一个错误还是一个功能,但我得到了关于它的警告,所以开发人员知道这个问题。

答案 1 :(得分:2)

受过教育的猜测:这绝对是预处理器中的一个错误,它的作用是忽略#endif之后的所有内容,无论如何都无法跟踪。

答案 2 :(得分:0)

如果我收到你的问题:

/*
#ifdef abcd
printf("what ever it is");
#endif */

您从头开始删除了“/ *”,代码无法编译?

这很好,因为代码不应该编译。如果没有开头,你的评论会更接近。

您可以做的是将“ /”替换为“// /”:

/*
#ifdef abcd
printf("what ever it is");
#endif //*/

这样你可以毫无问题地从头开始删除“/ *”。

答案 3 :(得分:0)

#endif */

这是块评论的结束,块评论开放在哪里?

/*

答案 4 :(得分:0)

首先,由于*/不是评论的一部分,因此在C 2011(n1570)5.1.1.2 1 3中描述的翻译阶段3中将其忽略。字符只是不变地传递。

因此,在阶段4(执行预处理程序指令)中,编译器会看到#endif */。根据C 2011(n1570)6.10 1,#endif指令的正确语法是:

# endif new-line

也就是说,它由三个预处理令牌#endif和一个换行符组成,在令牌之间允许使用空格和制表符。所以#endif */不是正确的语法。

如果源违反语法规则,5.1.1.3要求符合要求的实现生成诊断消息。因此,如果编译器在这种情况下不产生警告或错误消息,则它不符合。

某些编译器默认以不符合C标准的模式运行。您的编译器可能有开关来更改它,例如GCC的-std=c99开关。如果您的编译器在符合模式下没有发出警告或错误消息,那么这就是一个错误。