以这种方式包含头文件,这是一个好习惯吗?

在gumbo html parser source code中,我看到了一些#include像这样的奇怪用例。它们只是在数组定义块中包含头文件。

const char* kGumboTagNames[] = {
#include "tag_strings.h"
    "",  // TAG_UNKNOWN
    "",  // TAG_LAST
};

static const unsigned char kGumboTagSizes[] = {
#include "tag_sizes.h"
    0,  // TAG_UNKNOWN
    0,  // TAG_LAST
};

然后在tag_string.h文件中列出所有合法的 html 标签,

"html",
"head",
"title",
"base",
"link",
"meta",
"style",
"script",
"noscript",
...
...

我知道它有效,但仍然想知道这是导入外部数据的传统方式,还是只是一种不寻常的破解?

回答

如果您包含的数组内容是由其他某个进程自动生成的#include那么这是一种体面且有点传统的使用方式。(不过,还有其他方法可以做到,正如我将在下面提到的。)

这是一个经典的权衡。大多数情况下,一个值得遵循的好规则是,您应该以直接、传统的方式使用预处理器,因为当您开始变得“​​棘手”时,很容易造成一团糟。

但有时,您有一个数组,您确实希望使用一些自动的外部过程生成其内容。将数组定义复制并粘贴到源文件中既乏味又容易出错,您可能不得不在数组需要更新时不断重做。找出一种使过程自动化的方法是值得的,甚至可能值得违反“没有棘手的预处理器滥用”规则。

为了完成这项工作,您通常需要一些自动过程(可能是 awk、sed、perl 或 python 脚本)来生成具有正确语法的包含文件。如果您正在使用make或类似的东西,只要数组的实际源数据发生变化,您就可以自动执行该步骤。例如,在你给出的例子中,你可能有一个原始的“源文件”,tags.list其中包含像

html
head
title

然后在你的 Makefile 中使用类似的东西sed 's/.*/"&",'来创建具有正确字符串初始值设定项语法的包含文件。这样你就不会强迫更新列表的人记住总是使用正确的引号和逗号。

此外,正如其他评论员所建议的那样,您可能应该给文件一个以 以外的其他内容结尾的名称.h,以表明它不是包含完整、有效的 C 声明的普通头文件。在这种情况下.tab,更好的可能性是、.inc、 或.arr

不过,只要多做一点工作,您就可以避免“黑客攻击”并按常规方式执行大约 100% 的操作。如果您调整脚本以const char* kGumboTagNames[] = {在生成的文件的开头和};结尾添加该行,您可以给它一个以 结尾的名称.c,然后编译它,而不是包含它。(但是,这种方法会涉及其自身的权衡,因为它将数组限制为全局的,而不是静态的或本地的。)

脚注:在某些语言中——甚至在 C 和 C++ 中,在某些情况下——逗号用作分隔符,并且不允许在列表的最后一个元素之后使用逗号。但是在数组初始值设定项中,您可以使用尾随逗号,事实证明这是一个非常好的和有用的自由,正是因为它允许您使用像这里描述的那样简单的技术,而不必插入一个令人讨厌的删除列表中最后一个元素后的逗号的显式额外步骤。


以上是以这种方式包含头文件,这是一个好习惯吗?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>