【问题标题】:Can I split a long #include directive into two lines?我可以将长 #include 指令分成两行吗?
【发布时间】:2012-09-25 21:23:10
【问题描述】:

我希望有一种方法可以将 #include 指令拆分为两行,这样我的代码就可以符合每行 80 个字符的要求,尽管需要很长的包含路径。

除了扩展编译器的搜索路径,我该如何管理呢?有没有办法将我很长的路径字符串分成两行?

“#define”宏扩展显然发生在#include 扩展之后,所以这些不起作用:

#define BIGPATH "..."
#include BIGPATH ## "/foo.c"
#include "BIGPATH/foo.c"
#include BIGPATH"/foo.c"

我也试过

#include "foo" ##
         "bar"

#include "foo" \
         "bar"

无济于事。也许我想要的不可能?帮助我,stackoverflow kenobi,你是我唯一的希望。

回答:在下面建议的答案的基础上,以下是对我真正有用的方法:

#define STRINGIFY(x) #x
#define PATH(path) STRINGIFY(/my/very/long/path)
#include PATH(foo.h)
#undef PATH
#undef STRINGIFY

【问题讨论】:

  • 将您的目标目录符号链接到适合一行的内容。或者,设置包含路径,以便您只需要文件名,而不是整个路径。 (而且你不能用预处理器做你想做的事,它不会预处理预处理器指令。)
  • 宏扩展发生在包含扩展之前,否则#include SOME_ARG_FROM_USER(例如在 Boost.Preprocessor 中)将不起作用。
  • 长的绝对固定路径很难看,最好将它作为参数传递给预处理器,它会更加灵活,并且在路径挂起的那天给你带来更少的麻烦......例如检查 gcc 的 -I 选项
  • Avakar 对其中一个答案的评论暗示您的第三个答案几乎是正确的 - 尝试#include "foo\ (换行,下一行没有前面的空格)bar",并尽可能发布如果有,请回答。

标签: c include c-preprocessor stringification


【解决方案1】:

我不喜欢这个想法,我只是想提一下这种可能性。最好的方法是按照 Daniel Fischer 提到的方式进行。此解决方案有点古怪,并非在所有情况下都有效,但在这里编译:

#define PATH(FILE) </path/to/FILE>
#include PATH(file.h)

仅列举一些明显的限制:

  • 这些包含的搜索路径不是“本地”
  • 文件不得包含“,”(相当少见)
  • PATH 定义仍然可以超过 80 个字符

随时添加到此列表中。

编辑
为了更好的可读性,我将在下面以我的示例风格发布来自 Jonathans 评论的解决方案:

#define STRINGIFY(x) #x 
#define PATH(FILE) STRINGIFY(/path/to/FILE) 
#include PATH(foo.h)

此版本缓解了#include &lt;&gt; 版本的“局部性问题”,因为它映射到#include ""

【讨论】:

  • 这是最接近的,但我不得不根据自己的需要稍作修改:#define STRINGIFY(x) #x #define PATH(path) STRINGIFY(/my/very/long/path) #include PATH (foo.h) #undef 路径 #undef STRINGIFY
  • @JonathanMayer 如果这对您有用,请自行发布答案,而不是编辑不同的答案。 (如果您愿意,可以接受自己的)
【解决方案2】:

这是为我编译的(我基于我回忆 Boost.PP 的工作方式):

#define a() <vec\
tor>

#include a()

int main() {
  std::vector<int> x;
}

只需将 &lt;vector&gt; 更改为您的完整路径 - 我认为您不能像在 #include 中那样连接字符串。

【讨论】:

    【解决方案3】:

    使用另一个短名称的头文件来存储长名称的头文件。因此,所有超过 80 个字符的标题都不在您格式良好的代码中。

    //short_name.h
    #include "really_really_long_include_name.h"
    
    //code
    #include "short_name.h"
    

    【讨论】:

      【解决方案4】:

      所有预处理指令都由换行符终止。 include 指令是以下形式之一:

      # include < h-char-sequence> new-line
      # include " q-char-sequence" new-line
      # include pp-tokens new-line
      

      您的最后一个示例将导致执行 #include "foo" "bar" 的等效项,因为尽管转义的新行删除将在指令执行之前发生,但字符串连接会在之后发生。这与包含指令的最终有效形式相匹配。

      但是,这种形式的情况是include 后面的任何宏名称都将被替换。你的没有任何宏。如果生成的指令与正常的两种形式中的任何一种都不匹配,则行为未定义。

      如果在所有替换后产生的指令与前两种形式之一不匹配,则行为未定义

      该标准对存在多个字符串文字的情况有一个特定的注释:

      请注意,相邻的字符串文字不会连接成单个字符串文字(请参阅 2.2 中的翻译阶段);因此,导致两个字符串文字的扩展是无效指令。

      这就是为什么该示例不起作用的原因。然而,这确实意味着我们可以依靠宏扩展来生成有效的文件名。例如:

      #define LONG_PATH(file) <foo/bar/baz/file>
      #include LONG_PATH(file.h)
      

      或者:

      #define STRINGIZE(x) #x
      #define LONG_PATH(file) STRINGIZE(foo/bar/baz/file)
      #include LONG_PATH(file.h)
      

      【讨论】:

      • 宏是否在字符串文字中展开?
      【解决方案5】:

      不,您不能,预处理器要求包含文件名是单个预处理标记。您需要修复您正在使用的包含搜索路径,或者放宽每行 80 个字符的要求。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        • 2019-12-20
        • 2021-12-03
        • 1970-01-01
        • 2014-01-24
        • 1970-01-01
        相关资源
        最近更新 更多