c - 如何确定 foo.c 中的哪些预处理器宏源自 bar.h?

标签 c parsing static-code-analysis

我有两个 C 语言文件:foo.cbar.h(可能还有许多其他文件)。我想要一个在 foo.c 中使用并在 bar.h 中定义的所有预处理器宏的列表。

或者,如果这太困难,甚至可以提供出现在 foo.c 中的所有预处理器宏的列表(但任何标识符、单词或一段文本)和bar.h

我怎样才能获得它?

最佳答案

您可以从 gcc 预处理选项的输出中拼凑这些信息。

要获取文件实际使用的宏列表,您可以使用 -E -dU 选项,该选项会预处理文件,并且还包含 #define 命令任何宏的第一次使用。 (它还为使用 #ifdef#if Defined(...) 测试的未定义名称生成 #undef 命令。)(您必须使用-E 选项 - 仅预处理 - 以便正确处理 -dU。)

由于 -dU 不会抑制预处理输出,因此您需要通过仅查看 #define 指令来过滤它。对于某些应用程序,您可能还希望通过仅查看相关文件中的实际使用来进一步过滤它,因为报告还包括所包含文件对宏的使用。但在这种情况下,与头文件中实际定义的宏的交集可能就足够了。

因此,要获取 file.c 中使用的宏列表:

gcc -E -dU file.c | grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*'

(grep -Eo 删除宏的定义。)

您可以使用稍微更慷慨的 grep 调用来近似实际在头文件中定义的宏列表,如下所示:

grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' header.h

即使条件失败,它也会拾取条件部分中定义的宏,并且它将拾取注释中看起来像#define指令的行。通常,这些都不会造成很多问题。

您可以使用 gcc 的 -E -dM-E -dD 选项来获取 header 中所有定义的列表,但这两个选项也会插入由 header 包含的 header 定义的宏。 (-dM 还包括预定义的宏。)因此,您确实需要做更多的工作来关注头文件实际定义的宏,除非您对定义为包含头文件的结果。

然后你只需要找到两个列表的交集即可。一种方法是提取宏名称 (awk '{print $2}'),sort -u 独立地排序两个列表,然后合并它们,最后将它们都传递给 uniq -d 仅查看两个列表中的条目。 (以下两者都定义了您将调用 used_and_define foo.c bar.h 的 shell 函数 used_and_define)

used() {
  gcc -E -dU "$1" |
  grep -Eo '^#define [_A-Za-z][_A-Za-z0-9]*' |
  cut -f2 -d' ' |
  sort -u
}

defined() {
  grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$1" |
  awk '{ print $2 }' |
  sort -u
}

used_and_defined() {
  cat <(used "$1") <(defined "$2") | sort | uniq -d
}

或者您可以使用 awk 完成整个操作

used_and_defined() {
  awk '/^[[:space:]]*#[[:space:]]*define/ {
         gsub(/[ (].*/, "", $2);
         if (NR == FNR) ++macros[$2];
         else if (macros[$2]) print $2;
       }' \
       <(grep -Eo '^\s*#\s*define\s+[_A-Za-z][_A-Za-z0-9]*' "$2") \
       <(gcc -E -dU "$1")
}

关于c - 如何确定 foo.c 中的哪些预处理器宏源自 bar.h?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42900971/

相关文章:

c - 非阻塞Socket连接总是成功?

csv - 去CSV文件解析

c - 有人有使用 PC-Lint 和 Netbeans 或 MPLAB X IDE 的经验吗?

python - 将特定变量标记为已知

c++ - 我在 CppCheck 中发现了错误吗?为什么我会在此处收到 "Null pointer dereference"错误?

c - 将内核添加到 Windows 启动菜单

c - 在 emacs 中突出显示整个 c/cpp 宏定义?

python - 在新的 Python 源安装上运行 get-pip 后 undefined symbol

java - 在 java 中为 Android 应用程序解析 html

c - 从 C 文本文件中提取列表的列