C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
C语言中可用的标准预定义宏__FILE__显示文件的完整路径。有办法缩短这条路吗?我的意思是
/full/path/to/file.c
我看到
to/file.c
or
file.c
当前回答
我多年来一直使用@Patrick的答案。
当完整路径包含符号链接时,它有一个小问题。
更好的解决方案。
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D'__FILE__=\"$(subst $(realpath ${CMAKE_SOURCE_DIR})/,,$(abspath $<))\"'")
为什么要用这个?
-Wno-builtin-macro-redefined to mute the compiler warnings for redefining __FILE__ macro. For those compilers do not support this, refer to the Robust way below. Strip the project path from the file path is your real requirement. You won't like to waste the time to find out where is a header.h file, src/foo/header.h or src/bar/header.h. We should strip the __FILE__ macro in cmake config file. This macro is used in most exists codes. Simply redefine it can set you free. Compilers like gcc predefines this macro from the command line arguments. And the full path is written in makefiles generated by cmake. Hard code in CMAKE_*_FLAGS is required. There is some commands to add compiler options or definitions in some more recently version, like add_definitions() and add_compile_definitions(). These commands will parse the make functions like subst before apply to source files. That is not we want.
重新定义- wno -内置宏的健壮方法。
include(CheckCCompilerFlag)
check_c_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_C_WNO_BUILTIN_MACRO_REDEFINED)
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-Wno-builtin-macro-redefined SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
if (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined")
endif (SUPPORT_CXX_WNO_BUILTIN_MACRO_REDEFINED)
记住从集合(*_FLAGS…-D__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来说,这也会影响诊断消息中报告的文件名。
I think this is better than using strrchr function. strfnchr will search last delemeter '/' and get filename from __FILE__ and you can use __FILE__NAME__ instead __FILE__ for get file name without full file path. strrchr solution searching filename twice per use. but this code is just 1 time search. And it works effectively even if there is no seperater '/' in __FILE__. You can use it by replacing it with \ as needed. The source code of strfnchr was improved by using the source code of strrchr below. I think it will work more effectively than strrchr. https://code.woboq.org/userspace/glibc/string/strrchr.c.html
inline const char* strfnchr(const char* s, int c) {
const char* found = s;
while (*(s++)) {
if (*s == c)
found = s;
}
if (found != s)
return found + 1;
return s;
}
#define __FILE_NAME__ strfnchr(__FILE__, '/')
对于Visual Studio,您可以使用/d1trimfile选项。
你可能想把它设置为/d1trimfile:"$(SolutionDir)\":
注意:“”前面加了\的解释:
要转义第一个($(SolutionDir)以反斜杠结束),否则将转义引号。你需要等量的反斜杠 在引用之前。
纯粹的编译时解决方案。它基于这样一个事实:字符串字面量的sizeof()返回其长度+1。
#define STRIPPATH(s)\
(sizeof(s) > 2 && (s)[sizeof(s)-2] == '/' ? (s) + sizeof(s) - 1 : \
sizeof(s) > 3 && (s)[sizeof(s)-3] == '/' ? (s) + sizeof(s) - 2 : \
sizeof(s) > 4 && (s)[sizeof(s)-4] == '/' ? (s) + sizeof(s) - 3 : \
sizeof(s) > 5 && (s)[sizeof(s)-5] == '/' ? (s) + sizeof(s) - 4 : \
sizeof(s) > 6 && (s)[sizeof(s)-6] == '/' ? (s) + sizeof(s) - 5 : \
sizeof(s) > 7 && (s)[sizeof(s)-7] == '/' ? (s) + sizeof(s) - 6 : \
sizeof(s) > 8 && (s)[sizeof(s)-8] == '/' ? (s) + sizeof(s) - 7 : \
sizeof(s) > 9 && (s)[sizeof(s)-9] == '/' ? (s) + sizeof(s) - 8 : \
sizeof(s) > 10 && (s)[sizeof(s)-10] == '/' ? (s) + sizeof(s) - 9 : \
sizeof(s) > 11 && (s)[sizeof(s)-11] == '/' ? (s) + sizeof(s) - 10 : (s))
#define __JUSTFILE__ STRIPPATH(__FILE__)
请随意将条件操作符级联扩展到项目中最大的合理文件名。路径长度并不重要,只要检查距离字符串的末尾足够远。
我将看看我是否可以得到一个类似的宏,没有硬编码的长度与宏递归…
在MSVC中,将FILENAME宏作为FILENAME=%(FILENAME)%(扩展名)添加到c++项目的预处理器定义中。恐怕这完全是一个编译器杀手。它在某种程度上打破了并行构建。