C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是

/full/path/to/file.c

我看到

to/file.c

or

file.c

当前回答

在VC中,当使用/FC时,__FILE__展开为完整路径,不使用/FC选项__FILE__展开文件名。裁判:这里

其他回答

在MSVC中,将FILENAME宏作为FILENAME=%(FILENAME)%(扩展名)添加到c++项目的预处理器定义中。恐怕这完全是一个编译器杀手。它在某种程度上打破了并行构建。

下面是使用编译时计算的解决方案:

constexpr auto* getFileName(const char* const path)
{
    const auto* startPosition = path;
    for (const auto* currentCharacter = path;*currentCharacter != '\0'; ++currentCharacter)
    {
        if (*currentCharacter == '\\' || *currentCharacter == '/')
        {
            startPosition = currentCharacter;
        }
    }

    if (startPosition != path)
    {
        ++startPosition;
    }

    return startPosition;
}

std::cout << getFileName(__FILE__);

至少对于gcc, __FILE__的值是编译器命令行中指定的文件路径。如果你像这样编译file.c:

gcc -c /full/path/to/file.c

__FILE__将展开为“/full/path/to/file.c”。如果你这样做:

cd /full/path/to
gcc -c file.c

那么__FILE__将展开为“file.c”。

这可能是实际的,也可能不是。

C标准不要求这种行为。关于__FILE__,它只是将其扩展为“当前源文件的假定名称(字符串字面值)”。

另一种方法是使用#line指令。它覆盖当前行号,也可选择覆盖源文件名。如果你想覆盖文件名但保留行号,使用__LINE__宏。

例如,你可以把它添加到文件的顶部。c:

#line __LINE__ "file.c"

唯一的问题是它将指定的行号赋给下一行,而#line的第一个参数必须是一个数字序列,因此您不能执行类似的操作

#line (__LINE__-1) "file.c"  // This is invalid

确保#line指令中的文件名与文件的实际名称匹配作为练习。

至少对于gcc来说,这也会影响诊断消息中报告的文件名。

使用basename()函数,或者,如果是在Windows上,使用_splitpath()。

#include <libgen.h>

#define PRINTFILE() { char buf[] = __FILE__; printf("Filename:  %s\n", basename(buf)); }

还可以在shell中尝试man 3 basename。

一个简短的,适用于Windows和*nix的答案:

#define __FILENAME__ std::max<const char*>(__FILE__,\
    std::max(strrchr(__FILE__, '\\')+1, strrchr(__FILE__, '/')+1))