【问题标题】:Are tokens after #endif legal?#endif 之后的令牌是否合法?
【发布时间】:2011-03-28 13:32:50
【问题描述】:

我目前执行以下操作,编译器(MSVC2008 / 以及 2010)没有抱怨,但我不确定这是否是个坏主意:

#ifndef FOO_H_
#define FOO_H_

// note, FOO_H_ is not a comment:
#endif FOO_H_

我以前总是写成#endif // FOO_H_,但我发现自己今天没有这样做,并认为这很奇怪,因为显然我已经有一段时间没有使用评论方法了。

这是一种不好的做法,我应该返回所有的标题并修复(它是一个跨平台的应用程序)还是可以保持原样?

【问题讨论】:

  • 我收到 GCC 的警告(额外的令牌),所以我不建议这样做。
  • 我试图询问就标准而言,这是否是可接受的事情 - 或者它是否是特定于实施的或其他 - 我不太确定。也许最好的措辞是“这合适吗?” - 无论哪种方式,当应用程序在其他操作系统上编译时我都不希望出现警告,所以我会删除它们 - 谢谢。
  • @Joe:对不起,我读错了问题。
  • @GMan:完全没有问题^^ - 感谢您也更正标题:D
  • @Joe:你应该正确地@attribute评论答案,否则他们不会出现在你正在回复的人的回复列表中。

标签: c++ standards-compliance include-guards


【解决方案1】:

根据其他人发布的内容,我想我可以帮助您实际纠正问题。 (假设它在许多文件中。)

您可以使用 Visual Studio 中的查找和替换功能一次更正所有有问题的行。只需将 Find What: 设置为 "\#endif {[a-zA-Z\.\_]+}$" 并将 Replace With: 设置为 "#endif //\1" (并确保在 find 选项下选中 Use: [Regular Expressions]。)

并且在整个解决方案上这样做,你应该很高兴。

(请先备份您的项目,我已经对此进行了测试,它似乎按预期工作,但使用此项目需要您自担风险。)

【讨论】:

  • 哦,现在太棒了,我不知道您可以在查找和替换框中使用正则表达式。不过我对它们不是很好,它告诉我“模式中的语法错误”并突出显示“#endif {[a-zA-Z._]+}$” - 我做错了什么吗? -- 编辑:糟糕,不能在其中使用 # 否则它会破坏它。现在正在运行,非常感谢!
  • #, 前面应该有斜线()。和 _。不知道他们为什么被删除? (像这样:\#endif {[a-zA-Z\._]+}$)
  • @Joe.F 它删除了 _ 之前的那个。不知道为什么。只需重新添加它,你就会很好。
  • 啊!好吧,无论如何它似乎工作得很好,但我会使用备份并使用正确的备份以确保。非常感谢你 - 我必须把这个技巧放在手边,以防我再次搞砸:D
  • 我冒昧地编辑了您的帖子,以便可以看到反斜杠。 +1 我发布了一个实际的解决方案! @Joe:如果您必须备份您的项目,这表明您没有使用 SCM。这很糟糕,从长远来看会伤害你。
【解决方案2】:

为什么你的编译器应该警告你。

说你的头文件是这样的:

#ifndef X
#define X
// STUFF
// The next line does not contain an EOL marker (can happen)
#endif

现在您从源代码中包含此内容

#include "plop.h"
class X
{
}

当编译器在技术上包含该文件时,扩展的源代码应如下所示

#define X
// STUFF
// The next line does not contain an EOL marker (can happen)
#endif class X
{
}

大多数现代编译器都会考虑到他可能发生的情况,并在包含的文件上粘贴一个额外的 EOL 令牌以防止这种情况发生(技术上不允许,但我想不出会导致问题的情况)。

问题是一些较旧的编译器不提供这个额外的标记(更符合标准),但结果你可能最终编译上面的代码(结果他们倾向于警告你两件事 1)丢失源文件中的 EOL 和 2) #endif 之后的内容

【讨论】:

    【解决方案3】:

    严格来说(根据标准中的语法),在同一行上的 #endif 指令之后不允许使用任何标记(cmets 可以,因为它们在比预处理指令更早的翻译阶段被删除 - 阶段 3 vs . 4).

    但是,MSVC 似乎允许这样做 - 我不会继续寻求修复这些问题(因为它们不会造成问题),但可能会在您修改具有他们。

    当然,如果您的其他受支持的编译器发出有关它们的诊断信息,那么修复它们可能更为紧迫。

    【讨论】:

    • 我主要担心的是,当应用程序被移植到其他操作系统时,如果这种行为是不允许的,它可能会导致一些问题,因为它不是我会修复它。反正也不应该花那么长时间。不过谢谢!
    【解决方案4】:

    这是不行的,它是无效的,AFAIK。许多编译器会忽略#endif 之后的额外文本,并且经常会发出警告。您应该添加 // 以使其成为评论。

    【讨论】:

    • 好的,我不希望收到任何警告,所以我会回去修复它,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-12-12
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-14
    • 2016-04-20
    相关资源
    最近更新 更多