我发现gcc支持一个奇怪的函数定义,如:
static void add_define P3(char *, name, int, nargs, char *, exps)
使用-D__USE_FIXED_PROTOTYPES__进行编译。而我的vim taglist插件无法给出正确的结果。我试图弄清楚ctags的手册页,但我找不到它。
修改 是的,这很奇怪。宏是
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
并且评论告诉我这是
ANSI / K& R兼容性内容。
它打算安装AIX的c编译器xlc。
答案 0 :(得分:3)
使用如下所示的宏定义:
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
这个声明:
static void add_define P3(char *, name, int, nargs, char *, exps);
(我添加了一个尾随分号)扩展到:
static void add_define(char *name, int nargs, char *exps);
这是一个非常普通的函数原型(假设有一个尾随的分号)。
可能是该宏的替代版本,如下所示:
#define P3(t1, v1, t2, v2, t3, v3) \
(v1, v2, v3) \
t1 v1; \
t2 v2; \
t3 v3;
将扩展为:
static void add_define(name, nargs, exps)
char *name;
int nargs;
char *exps
这是K& R风格的非原型函数声明。
可能有类似的东西:
#ifdef __STDC__
#define P3(t1, v1, t2, v2, t3, v3) (t1 v1, t2 v2, t3 v3)
#else
#define P3(t1, v1, t2, v2, t3, v3) \
(v1, v2, v3) \
t1 v1; \
t2 v2; \
t3 v3;
#endif
以及类似的宏P0,P1,P2等,用于不同数量的参数。或者,正如您在问题中所暗示的那样,它使用用户定义的宏__USE_FIXED_PROTOTYPES__
而不是__STDC__
。
这将允许单个声明自动扩展为现代原型或K& R风格的声明;只有非常旧的ANSI前编译器才需要后者。
要回答标题中的问题(最后!),ctags
对非预处理的C源进行操作。使用GNU ctags
进行的快速实验表明,解释隐藏基本语法的宏并不是特别聪明。它将为宏定义本身生成标记条目,但不会识别
static void add_define P3(char *, name, int, nargs, char *, exps) {
/* ... */
}
作为函数定义。 (您可以通过预处理器运行源文件,但随后标记将引用预处理文件,这不是特别有用。)原则上,ctags
应该理解完整的C语法,包括预处理器;在实践中,它没有。
如果您想为源文件生成ctags
生成标记,则需要删除宏并编写可识别的原型。您将无法使用预ANSI编译器编译修改后的源代码,但现在这不太可能成为问题。如果您能够执行此操作,则生成的代码应该更易于维护。
或者,由于ctags
生成的输出相当简单,因此将相关标记手动添加到tags
文件应该不会太困难(尽管自动维护它可能很困难)。