对于源级别分析,我需要扩展除#include
之外的宏,是否可能?
例如,在以下代码段中,我只希望将assert
扩展为__assert_fail
,而不是包含assert.h
并展开assert
。
#include <assert.h>
int main(void) {
assert(0); // expand this
return 0;
}
答案 0 :(得分:5)
如果您正在使用gcc,则使用-E
作为开关,只需在文件上运行预处理器。这将扩展文件中找到的所有宏,但保持源的其余部分不变。此外,您可以使用-U
统一在源中展开的任何宏。请参阅GCC preprocessor。
所以,在这:
#include <assert.h>
int main(int argc, char * argv[])
{
assert(0);
return 0;
}
调用:
g++ -E assert_test.cpp -o assert_test.ii
返回assert_test.ii:
# 1 "assert_test.cpp"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 30 "/usr/include/stdc-predef.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/predefs.h" 1 3 4
# 31 "/usr/include/stdc-predef.h" 2 3 4
# 1 "<command-line>" 2
# 1 "assert_test.cpp"
# 1 "/usr/include/assert.h" 1 3 4
# 36 "/usr/include/assert.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 371 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
# 385 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/bits/wordsize.h" 1 3 4
# 386 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 2 3 4
# 372 "/usr/include/features.h" 2 3 4
# 395 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 1 3 4
# 10 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/gnu/stubs-64.h" 1 3 4
# 11 "/usr/include/x86_64-linux-gnu/gnu/stubs.h" 2 3 4
# 396 "/usr/include/features.h" 2 3 4
# 37 "/usr/include/assert.h" 2 3 4
# 67 "/usr/include/assert.h" 3 4
extern "C" {
extern void __assert_fail (const char *__assertion, const char *__file,
unsigned int __line, const char *__function)
throw () __attribute__ ((__noreturn__));
extern void __assert_perror_fail (int __errnum, const char *__file,
unsigned int __line, const char *__function)
throw () __attribute__ ((__noreturn__));
extern void __assert (const char *__assertion, const char *__file, int __line)
throw () __attribute__ ((__noreturn__));
}
# 2 "assert_test.cpp" 2
int main(int argc, char * argv[])
{
((0) ? static_cast<void> (0) : __assert_fail ("0", "assert_test.cpp", 5, __PRETTY_FUNCTION__));
return 0;
}
所以,至少在我的系统上:
assert(0);
扩展为以下内容:
((0) ? static_cast<void> (0) : __assert_fail ("0", "assert_test.cpp", 5, __PRETTY_FUNCTION__));
其中__assert_fail
是外部定义的函数(通常包含libc
);因此,要回答您的问题,您可以使用自己喜欢的文本替换(sed / awk / perl)实用程序并将assert(xyz);
扩展为((xyz) ? static_cast<void> (xyz) : __assert_fail ("xyz", "<file_name>", 5, __PRETTY_FUNCTION__));
答案 1 :(得分:1)
您必须编写自己的预处理器。如果你按照简单的规则(大多数人这样做)将你的包括在顶部,那就不应该太难了。
事实上,在使用操作系统附带的命令行工具的shell脚本中,这一切都应该很容易。
如果你不遵循“包含在最高规则”,那将只会有点困难。您可以在每个include指令(或每组连续的include指令)之前和之后插入标记行,跟踪哪些指令在哪些标记之间。