Gcc 如何在预处理器中只获取文件名?

Gcc 如何在预处理器中只获取文件名?,gcc,c-preprocessor,filenames,Gcc,C Preprocessor,Filenames,我正在(曾经)使用\uuu文件\uuuuu和\uuuu行\uuuuu宏从我的代码中打印诊断消息。当您将GCC与make一起使用时,这种方法非常有效,文件的长度与您在命令行中指定的长度相同。我最近转而使用CodeLite,它在构建时使用完全限定的文件名(至少在windows下)。突然,我的诊断输出几乎无法读取 有没有办法在预处理器中只获取文件名的文件组件?我可以接受不可移植的特定于GCC的解决方案。(我将退回到普通的\uuuuu文件\uuuuuu其他情况。) 当然,我可以通过一个函数传递\uuuu

我正在(曾经)使用
\uuu文件\uuuuu
\uuuu行\uuuuu
宏从我的代码中打印诊断消息。当您将GCC与make一起使用时,这种方法非常有效,文件的长度与您在命令行中指定的长度相同。我最近转而使用CodeLite,它在构建时使用完全限定的文件名(至少在windows下)。突然,我的诊断输出几乎无法读取

有没有办法在预处理器中只获取文件名的文件组件?我可以接受不可移植的特定于GCC的解决方案。(我将退回到普通的
\uuuuu文件\uuuuuu
其他情况。)

当然,我可以通过一个函数传递
\uuuuuu FILE\uuuu
的内容,并仅提取文件组件,但对于不应改变运行时行为的诊断消息,字符串操作并不是我所想到的


注意:我使用文件名的方式与GNU使用文件名的方式相同。路径是文件名的集合,文件名是文件的相对或绝对标识符。文件名可以由目录组件和文件组件组成。

没有提供此功能的已知预处理器宏。通过函数传递
\uu FILE\uuu
是唯一明智的选择。

如果您使用的是GNU Make,那么您只需在编译的预处理阶段传递-D BASE\u FILE\u NAME=\“$*.c\”(如果您单独进行,或者在编译阶段传递,如果在单个阶段,这是正常的)

这取决于确定文件名的方式。我的文件名来自一个普通文件名列表,并在后面使用makefile中的函数以目录作为前缀

IE,这对我来说很好,但您的里程可能会有所不同!:-)

我的make“代码”的简化版本:

CLASSES=main.c init.c
预处理=$(patsubst%.c,$(PPCDIR)/%.pp.c,$(类))
$(预处理):$(PPCDIR)/%。pp.c:%.c$(全部)
$(GCC)$(GCCOPTS)-D基本\u文件名=\“$*\”-E$<>$@

代码中的简单使用基本文件名,如您所愿:-)

在回复上述FredCooke时,您可以交换此行:

-D BASE_FILE_NAME=\"$*.c\"
与:


-D BASE\u FILE\u NAME=\”$(如其他答案中所述,唯一可移植的方法是从编译器中传入一个define,但是有编译器特定的扩展名:

  • 叮当声:文件名
  • GCC:
    \uuuuu基本文件\uuuuuuu

诊断确实会更改运行时行为(否则将没有诊断),以及是否调用一个额外的函数没有什么区别,因为输出本身正在调用库函数来执行输出。打印诊断消息通常包括几十个字符串操作,以及一些不太好的文件I/O操作。出于某种原因,似乎没有人担心这一点。为什么要担心adding调用另一个只影响诊断消息的无副作用函数?你们都是对的,添加诊断不是无效果的。我是这样实现的,我让它通过一个函数传递。我更想知道它是否存在。它肯定不是标准的,但找到有关这方面的文档并不完美。(即使是gcc手册也没有列出每个预定义的宏。)关于I/O;不是每个诊断都必须打印到STDOUT/STDERR或文件。听说过应用程序崩溃时输出的环形缓冲区吗?例如,GNU Nana实现了这一点。与“几乎“没有影响性能。FC++还有C++CistExPR解决方案:不幸的是我正在使用CaldLITE,它为我生成了Maxfile。使用CaldRITE是非常棒的,直到你想做一些不符合标准的事情。仍然不错的IDEA,+1同样的想法可以在VisualStudio中使用。在Visual Studio 2008中:右击项目文件。(.vcproj)->属性->配置属性->C/C++->预处理器->预处理器定义。添加基本文件“$(InputFileName)\”。您可以使用uuu BASE_文件而不是源文件中的文件。对于gcc,有。@fret:对于我来说,
\uuuuu BASE_文件uuu
的输出与
\uuuu文件uuuu
相同。如果您阅读链接到的文档,它会使用
main
函数(甚至不是当前文件)提供文件的名称(不一定是basename)如果你可以使用C++,那么有一个CONTXPR解决方案:@ TrevorBoydSmith好点。但是,老实说,如果你查看日期,这个问题在C++ 11发布一个月后被问及还没有被广泛采用。
-D BASE_FILE_NAME=\"$*.c\"
-D BASE_FILE_NAME=\"$(<F)\"